过久没打cf了,赛时只作出来3道QAQ,读题和手速如今慢的离谱,只能靠赛后补题来弥补了......html
A. Dense Arrayios
数据很小直接模拟插入便可,x = min(a[i],a[i+1]) y = min(a[i],a[i+1])数组
若是 y >= 2 * x , 不须要操做ide
不然不断插入 2 * x 直到知足条件,最后统计一下插入2x 的数量便可函数
#include<iostream> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; int t,n,m; int a[104]; #define sz std::ios::sync_with_stdio(false) int main() { sz; cin >> t; while(t--){ int cnt = 0; cin >> n; for(int i = 1; i <= n; i++){ cin >> a[i]; } for(int i = 1; i < n; i++){ int k = 1; int minn = min(a[i+1],a[i]); int maxx = max(a[i+1],a[i]); if(maxx <= 2 * minn){ continue; } else{ while(maxx > 2 * minn){ minn *= 2; cnt++; } } } cout << cnt << endl; } }
B. Balanced Remaindersui
记录一下数列中除3余1,2,0 的个数,由题意可知,每次操做有如下结果:余0->余1 余1->余2 余2->余0spa
为了使其都变成n/3,咱们能够从前日后推下去,增长个数向前一个数借,减小个数给下一位,模拟这一过程直到每一个数都为n/3便可code
#include<iostream> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; int t,n,m; int a[104]; int c[5]; #define sz std::ios::sync_with_stdio(false) int main() { sz; cin >> t; while(t--){ int ans = 0; cin >> n; memset(c,0,sizeof(c)); for(int i = 0; i < n; i++){ int x; cin >> x; c[x % 3]++; } int m = n / 3; for(int i = 0; i < 3; i++){ if(c[i] > m){ if(i == 2){ c[0] += c[i]-m; } else{ c[i+1] += c[i]-m; } ans += c[i]-m; c[i] = m; } else if(c[i] < m){ if(i == 0){ c[2] -= (m - c[i]); } else{ c[i - 1] -= (m - c[i]); } ans += (m - c[i]); c[i] = m; } } cout << ans << endl; } }
C. Sum of Cubesorm
数据大小为1e12,那么立方数最大为1e4,能够先预处理用数组存储一下1e4个立方数,以后就枚举数组的每一个数,二分查找判断其相减获得的另外一个数是否为立方数。htm
#include<iostream> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; int t,n,m; ll x; ll a[10004]; int tt; bool c[10004]; #define sz std::ios::sync_with_stdio(false) void unit(){ for(ll i = 1; i <= 10000; i++){ a[++tt] = i * i * i; } } int main() { unit(); cin >> t; while(t--){ cin >> x; bool judge = 0; for(int i = 1; i <= tt; i++){ ll xx = a[i]; ll yy = x - xx; if(yy <= 0){ break; } ll pos = lower_bound(a+1,a+1+tt,yy) - a; if(a[pos] == yy){ judge = 1; break; } } if(judge) cout << "YES\n"; else cout << "NO\n"; } }
D. Permutation Transformation
模拟建树,用in数组记录每一个元素对应下标,查找区间最大值能够用线段树logn查找maxn,而后利用in数组经过maxn找到其对应的下标,以该下标为父节点递归建左子树右子树。
#include<iostream> using namespace std; int tt,n,m; struct Hi{ int maxx; int l,r; }t[1000000]; int a[1000005]; int ans[1000004]; int in[100006]; // int a[] = {3,5,8,1,4,2}; void built(int i,int l,int r){ t[i].l = l; t[i].r = r; if(l == r){ t[i].maxx = a[l]; return; } int mid = (l + r) / 2; built(i * 2,l,mid); built(i * 2 + 1,mid + 1,r); t[i].maxx = max(t[i * 2].maxx,t[i * 2 + 1].maxx); } int findmax(int i,int l,int r,int ll,int rr) { if(ll <= l && rr >= r) return t[i].maxx; else if(ll > r || rr < l) return 0; else{ int mid = (l + r) / 2; return max(findmax(i * 2,l,mid,ll,rr), findmax(i * 2 + 1,mid+1,r,ll,rr)); } } void work(int dep,int l,int r) { int num = findmax(1,0,n-1,l,r); ans[in[num]] = dep; if(l < in[num]) work(dep+1,l,in[num] - 1); if(in[num] + 1 <= r) work(dep+1,in[num] + 1,r); } int main() { cin >> tt; while(tt--){ cin >> n; for(int i = 0; i < n; i++){ cin >> a[i]; in[a[i]] = i; } built(1,0,n-1); work(0,0,n-1); for(int i = 0; i < n; i++){ cout << ans[i] << " "; } cout << "\n"; } }
E. Accidental Victory
先对全部人按照货币升序进行排序获得数组a,再对排序后的数组进行前缀和获得数组f。
此时f[i]能够看作第i人能得到的最大货币(即赢了前面全部人),让其与a[i+1]进行比较大小,若是比a[i+1]大,那么他能够继续成为赢家,货币总值变为f[i+1],如此看来某我的为了成为最后赢家,其前缀和要每次都比下一我的的货币多,所以咱们能够从货币量最多的人开始向前判断,遇到第一个不能向后扩展的人结束,途径的人均可以成为赢家。
#include<iostream> #include<cstring> #include<algorithm> #include<map> #include<vector> using namespace std; typedef long long ll; int t,n,m; ll x; struct Hi{ ll num; ll id; }a[2000004]; ll f[200005]; vector<int>v; map<int,int>mm; #define sz std::ios::sync_with_stdio(false)int cmp(Hi A,Hi B){ return A.num < B.num; } int main() { sz; cin >> t; while(t--){ mm.clear(); cin >> n; // v.clear(); for(int i = 1; i <= n; i++){ cin >> a[i].num; a[i].id = i; } sort(a+1,a+1+n,cmp); for(int i = 1; i <= n; i++){ f[i] = f[i-1] + a[i].num; } ll ans = 1; mm[a[n].id] = 1; for(int i = n - 1; i >= 1; i--){ if(f[i] >= a[i+1].num){ ans++; // v.push_back(a[i].id); mm[a[i].id] = 1; } else{ break; } } cout << ans << "\n"; for(int i = 1; i <= n; i++){ if(mm[i] == 1){ cout << i << " "; } } cout << "\n"; } }
F. Equalize the Array
一言不合先排序,而后统计一下每一个值的出现次数,放入vector容器中,再来排序。
此时有点像在升序阶梯中求最大矩阵,能够用单调栈进行解决,不过这里直接从前日后进行模拟更新v[i] * ((int)v.size() - i)的最大值便可,遍历过程当中记得统计一下cnt值,而后cnt-max(v[i] * ((int)v.size() - i))就是答案了!
#include<iostream> #include<cstring> #include<algorithm> #include<map> #include<set> #include<vector> using namespace std; typedef long long ll; #define sz std::ios::sync_with_stdio(false) int t,n,m; ll a[200005],f[200004]; int main() { sz; cin >> t; while(t--){ vector<int>v; cin >> n; for(int i = 1; i <= n; i++){ cin >> a[i]; } a[n + 1] = 0x3f3f3f; sort(a+1,a+1+n); int cnt = 0; for(int i = 1; i <= n+1; i++){ if(i == 1){ cnt++; } else if(a[i] == a[i-1]){ cnt++; } else{ v.push_back(cnt); cnt = 1; } } sort(v.begin(),v.end()); int ans = -1; cnt = 0; for(int i = 0; i < v.size(); i++){ cnt += v[i]; ans = max(ans,v[i] * ((int)v.size() - i)); } cout << cnt - ans << "\n"; } }
G. Old Floppy Drive
这题看了某位大佬题解才明白怎么作的orz,原来是二分模拟,看题的时候怎样都想不到二分的作法QAQ太菜了
@https://www.cnblogs.com/lipoicyclic/p/14411008.html 大佬的题解直接放下来了
不妨设sum数组为前缀和数组,mx[i]表明前缀和数组里1~i最大的一个前缀和(由于可能有负数,前缀和数组不必定是单调不减,但mx数组必定是单调不减的,因此利用mx数组来进行二分查找)。
若是mx[n] >= x,说明只遍历一遍前缀和数组必定能找到一个位置知足条件,直接在mx用lower_bound二分查找x便可。
若是mx[n] < x:意味着只遍历一轮不够。
首先,若是sum[n] <= 0,说明确定是越更新越小(联想spfa判负环),永远也不可能中止,直接输出-1.
若是sum[n] > 0,设d = x - mx[n],则至少要循环ceil(d / sum[n])圈。可是向上取整以后在最后一圈就不必定是到mx[n]了,有可能在下标更小的位置就结束循环,这个位置能够根据lower_bound函数查找x - ceil(d * 1.0 / sum[n]) * sum[n],再加上 ceil(d * 1.0 / sum[n]) * n(每轮移动n次)便可。
#include<iostream> #include<cstring> #include<algorithm> #include<map> #include<set> #include<cmath> #include<vector> using namespace std; typedef long long ll; #define sz std::ios::sync_with_stdio(false) ll n,t,m; ll mm[200004]; ll a[200005]; ll f[200005]; int main() { sz; cin >> t; while(t--){ cin >> n >> m; f[0] = 0; mm[0] = 0; for(int i = 1; i <= n; i++) { cin >> a[i]; f[i] = f[i - 1] + a[i]; mm[i] = max(mm[i - 1], f[i]); } for(int i = 1; i <= m; i++) { ll x; cin >> x; if(mm[n] >= x){ cout << lower_bound(mm + 1, mm + n + 1, x) - 1 - mm << ' '; } else { if(f[n] <= 0) { cout << -1 << ' '; continue; } long long d = x - mm[n]; cout << lower_bound(mm + 1, mm + n + 1, x - f[n] * (long long)ceil(d * 1.0 / f[n])) -mm - 1 + (long long)ceil(d * 1.0 / f[n]) * n << ' '; } } cout << endl; } }
end~
终于补完(第一次啊),下次加油啦!但愿下次div3能手速过前4题,不要那么慢了呀。