Codeforces 786C Till I Collapse 线段树
对于每个 k, 考虑贪心地取, 最多分成 n / k段, 每段都贪心取的话, 总次数为nlogn
用线段树维护这个过程, 在线段树上二分就可以了。
#include<bits/stdc++.h> #define LL long long #define LD long double #define ull unsigned long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ALL(x) (x).begin(), (x).end() #define fio ios::sync_with_stdio(false); cin.tie(0); using namespace std; const int N = 1e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 998244353; const double eps = 1e-8; const double PI = acos(-1); template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;} template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;} template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;} template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;} int n, a[N]; int nex[N]; int Map[N]; int ans[N]; bool vis[N]; namespace SGT { #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 int a[N << 2]; void update(int p, int val, int l, int r, int rt) { if(l == r) { a[rt] += val; return; } int mid = l + r >> 1; if(p <= mid) update(p, val, lson); else update(p, val, rson); a[rt] = a[rt << 1] + a[rt << 1 | 1]; } int query(int res, int l, int r, int rt) { if(l == r) return l; int mid = l + r >> 1; if(a[rt << 1] > res) return query(res, lson); else return query(res - a[rt << 1], rson); } } int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); for(int i = n; i >= 1; i--) { nex[i] = Map[a[i]]; vis[nex[i]] = true; Map[a[i]] = i; } priority_queue<PII, vector<PII>, greater<PII> > que; for(int i = 1; i <= n; i++) que.push(mk(1, i)); for(int i = 1; i <= n; i++) if(!vis[i]) SGT::update(i, 1, 1, n + 1, 1); for(int i = 1; i <= n; i++) { while(!que.empty() && que.top().fi == i) { int qid = que.top().se; que.pop(); ans[qid]++; int nexpos = SGT::query(qid, 1, n + 1, 1); que.push(mk(nexpos, qid)); } SGT::update(i, -1, 1, n + 1, 1); if(nex[i]) SGT::update(nex[i], 1, 1, n + 1, 1); } for(int i = 1; i <= n; i++) printf("%d%c", ans[i], " \n"[i == n]); return 0; } /* */