過久沒打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題,不要那麼慢了呀。