http://codeforces.com/contest/1065/problem/C
题意:给你n个高度分别为a[i]的塔,每次可以横着切一刀,切掉不多于k个塔,问最少切多少刀才能把塔切的都一样高(k>=n)
高度和n都在2*10^5以内
思路:既然高度在20w以内嘛 那就按高度模拟惹 然鹅该怎么模拟着实头疼了一下下
用a[i] 记录高度为i-1时,有多少个塔有高度,如果当前高度为i-1时有a[i]个塔,并且a[i]<k,那么可以去考虑下一层
用sum记录上一层之前还有多少没切,比较sum+a[i]和k的大小可以决定切不切,切的话就cnt++,剩的sum就是a[i](因为是sum+a[i]>k时切的
然后就是a[i]怎么算出来的问题了嘤嘤嘤
用了桶排序(?)和前缀和(?)类似的思想(?)←开始瞎bb
因为越往高,塔数肯定不减,输入每个高度的时候记录一下到这个高度时,塔数要-1(a[h]--), 然后a[0]=n, a[i] += a[i-1],一个个往后加就可以了
#include <stack> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; const int maxn = 200010; const int INF = 1000000100; int a[maxn]; int main() { int n, k; scanf("%d%d", &n, &k); int maxh = 0; for(int i = 1; i <= n; i++) { int h; scanf("%d", &h); maxh = max(h, maxh); a[h]--; } a[0] = n; for(int i = 0; i <= maxh; i++) a[i] += a[i-1]; int cnt = 0, res = 0; for(int i = maxh; i >= 0; i--) { if(a[i] == n) { if(res) cnt++; break; } if(res + a[i] > k) { cnt++; res = a[i]; } else res += a[i]; } printf("%d ", cnt); return 0; }