luogu P2617 Dynamic Rankings && bzoj 1901 (带修改区间第k大)
链接:https://www.luogu.org/problemnew/show/P2617
思路:
如果直接在主席树上修改的话,每次修改都会对后面所有的树造成影响,一次修改的复杂度就会变成 : n*logn,我们套上树状数组维护,每次就最多只用更新logn棵树,复杂度是:logn*logn,是可以接受的;
代码参考hzwer: http://hzwer.com/2835.html
实现代码;
#include<bits/stdc++.h> using namespace std; const int M = 2e5+10; int v[M],num[M*2],has[M*2]; int op[M],A[M],B[M],K[M],rt[M]; int sum[M*170],ls[M*170],rs[M*170]; int L[40],R[40],a,b,tot,idx,k; int lowbit(int x){ return x&(-x); } int find(int x){ int l = 1,r = tot; while(l <= r){ int mid = (l + r) >> 1; if(has[mid] < x) l = mid + 1; else r = mid - 1; } return l; } void update(int old,int &k,int p,int c,int l,int r){ k = ++idx; ls[k] = ls[old],rs[k] = rs[old]; sum[k] = sum[old] + c; if(l == r) return ; int mid = (l + r) >> 1; if(p <= mid) update(ls[old],ls[k],p,c,l,mid); else update(rs[old],rs[k],p,c,mid+1,r); } int query(int l,int r,int k){ if(l == r) return l; int suml = 0,sumr = 0; for(int i = 1;i <= a;i ++) suml += sum[ls[L[i]]]; for(int i = 1;i <= b;i ++) sumr += sum[ls[R[i]]]; int mid = (l + r) >> 1; if(sumr - suml >= k){ for(int i = 1;i <= a;i ++) L[i] = ls[L[i]]; for(int i = 1;i <= b;i ++) R[i] = ls[R[i]]; return query(l,mid,k); } else { for(int i = 1;i <= a;i ++) L[i] = rs[L[i]]; for(int i = 1;i <= b;i ++) R[i] = rs[R[i]]; return query(mid+1,r,k-(sumr-suml)); } } int main() { int n,m,cnt = 0; scanf("%d%d",&n,&m); for(int i = 1;i <= n;i ++){ scanf("%d",&v[i]); num[++cnt] = v[i]; } char s[10]; for(int i = 1;i <= m;i ++){ scanf("%s",s); scanf("%d%d",&A[i],&B[i]); if(s[0]=='Q') scanf("%d",&K[i]),op[i] = 1; else num[++cnt] = B[i]; } sort(num+1,num+cnt+1); has[++tot] = num[1]; for(int i = 2;i <= cnt;i ++){ if(num[i] != num[i-1]) has[++tot] = num[i]; } for(int i = 1;i <= n;i ++){ int k = find(v[i]); for(int j = i;j <= n;j += lowbit(j)) update(rt[j],rt[j],k,1,1,tot); } for(int i = 1;i <= m;i ++){ if(op[i]){ a = 0; b = 0; A[i]--; for(int j = A[i];j > 0;j -= lowbit(j)) L[++a] = rt[j]; for(int j = B[i];j > 0;j -= lowbit(j)) R[++b] = rt[j]; printf("%d\n",has[query(1,tot,K[i])]); } else{ int k = find(v[A[i]]); for(int j = A[i];j <= n;j += lowbit(j)) update(rt[j],rt[j],k,-1,1,tot); v[A[i]] = B[i]; k = find(B[i]); for(int j = A[i];j <= n;j += lowbit(j)) update(rt[j],rt[j],k,1,1,tot); } } return 0; }