P2617 Dynamic Rankings | 整體二分
阿新 • • 發佈:2020-11-21
題目簡述
給一個長度為\(n\)的序列\(a_1,a_2,\cdots a_n\),有\(m\)個操作,為以下兩種:
- \(x,k\) \(a_x \leftarrow k\)
- \(l,r,k\) 求區間\([l,r]\)內的第\(k\)小
\(n,m \le 10^5\).
簡單口胡
首先這題毒瘤資料結構是完全可做的。
但是考慮到我可能不會,於是整體二分。
有修改的整體二分其實和無修的差不多,多了一個將原來的改為\(-1\)的過程。
# include <bits/stdc++.h> using namespace std; const int N = 2e5 + 5; int n,m; int a[N << 1]; struct node { int l,r,k,type,soc; node(){} node(int _l,int _r,int _k,int _ty,int _soc) : l(_l),r(_r),k(_k),type(_ty),soc(_soc) {} }Q[N << 1],q1[N << 1],q2[N << 1]; int tot = 0,qtot = 0,ans[N << 1]; struct BIT { int lowbit(int x) {return x & (-x);} int a[N]; void add(int x,int d) {while(x <= n) {a[x] += d;x += lowbit(x);}} int query(int x) { int ans = 0; while(x) {ans += a[x];x -= lowbit(x);} return ans; } }T; template <typename T> void read(T &x) { int w = 1; x = 0; char ch = getchar(); while(!isdigit(ch)) { if(ch == '-') w = -1; ch = getchar(); } while(isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); } x *= w; } template <typename T> void write(T x) { if(x < 0) x = -x; if(x >= 10) write(x / 10); char ch = (x % 10) + 48; putchar(ch); return; } void qfind(int l,int r,int s,int t) { if(l > r || s > t) return; if(l == r) { for(int i = s; i <= t; i++) { if(Q[i].type == 2) ans[Q[i].soc] = l; } return; } int mid = (l + r) >> 1; int cur1 = 0,cur2 = 0; for(int i = s; i <= t; i++) { if(Q[i].type == 1) { if(Q[i].l <= mid) { T.add(Q[i].soc,Q[i].k); q1[++cur1] = Q[i]; } else q2[++cur2] = Q[i]; } else { int sum = T.query(Q[i].r) - T.query(Q[i].l - 1); if(sum >= Q[i].k) { q1[++cur1] = Q[i]; } else { Q[i].k -= sum; q2[++cur2] = Q[i]; } } } for(int i = 1; i <= cur1; i++) { if(q1[i].type == 1) { T.add(q1[i].soc,-q1[i].k); } } for(int i = 1; i <= cur1; i++) Q[s + i - 1] = q1[i]; for(int i = 1; i <= cur2; i++) Q[s + i + cur1 - 1] = q2[i]; qfind(l,mid,s,s + cur1 - 1); qfind(mid + 1,r,s + cur1,t); return; } int main(void) { read(n),read(m); for(int i = 1; i <= n; i++) { read(a[i]); Q[++tot] = node(a[i],0,1,1,i); } for(int i = 1; i <= m; i++) { char opt[2]; scanf("%s",opt); int l,r,k; if(opt[0] == 'C') { read(l),read(k); Q[++tot] = node(a[l],0,-1,1,l); Q[++tot] = node(a[l] = k,0,1,1,l); } else { read(l),read(r),read(k); Q[++tot] = node(l,r,k,2,++qtot); } } qfind(0,1e9,1,tot); for(int i = 1; i <= qtot; i++) { write(ans[i]); putchar('\n'); } return 0; }