BZOJ 1901: Zju2112 Dynamic Rankings | 带修改主席树
题目:
emmmm是个权限题
题解:
带修改主席树的板子题,核心思想是用树状数组维护动态前缀和的性质来支持修改
修改的时候修改类似树状数组一样进行logn个Insert
查询的时候同理,树状数组的方法取出和这个位置相关的节点,用数组保存然后计算
#include<cstdio> #include<algorithm> #include<cstring> #define N 100005 #define M 6000005 using namespace std; int n,m,a[N],lst[N],idx; int tot,root[N],data[M],ls[M],rs[M],cur1[N],cur2[N]; int qtype[N],q1[N],q2[N],q3[N]; char s[233]; void build(int &k,int l,int r) { k=++tot; if (l==r) return; int mid=l+r>>1; build(ls[k],l,mid),build(rs[k],mid+1,r); } void change(int x,int &y,int l,int r,int p,int k) { data[y=++tot]=data[x]+k,ls[y]=ls[x],rs[y]=rs[x]; if (l==r) return; int mid=l+r>>1; if (p<=mid) change(ls[x],ls[y],l,mid,p,k); else change(rs[x],rs[y],mid+1,r,p,k); } void add(int p,int num,int x) { for (;p<=n;p+=p&-p) change(root[p],root[p],1,idx,num,x); } int query(int ql,int qr,int k) { int l=1,r=idx; for (int p=ql;p;p-=p&-p) cur1[p]=root[p]; for (int p=qr;p;p-=p&-p) cur2[p]=root[p]; while (l<r) { int mid=l+r>>1,sum1=0,sum2=0; for (int p=ql;p;p-=p&-p) sum1+=data[ls[cur1[p]]]; for (int p=qr;p;p-=p&-p) sum2+=data[ls[cur2[p]]]; if (sum2-sum1>=k) { for (int p=ql;p;p-=p&-p) cur1[p]=ls[cur1[p]]; for (int p=qr;p;p-=p&-p) cur2[p]=ls[cur2[p]]; r=mid; } else { l=mid+1,k-=sum2-sum1; for (int p=ql;p;p-=p&-p) cur1[p]=rs[cur1[p]]; for (int p=qr;p;p-=p&-p) cur2[p]=rs[cur2[p]]; } } return lst[l]; } int getpos(int x) { return lower_bound(lst+1,lst+idx+1,x)-lst; } bool isQ() { char c; while(c=getchar(),c!='Q' && c!='C'); return c=='Q'; } int main() { scanf("%d%d",&n,&m),idx=n; for (int i=1;i<=n;i++) scanf("%d",&a[i]),lst[i]=a[i]; for (int i=1;i<=m;i++) { qtype[i]=isQ(); scanf("%d%d",q1+i,q2+i); if (qtype[i]) scanf("%d",q3+i); else lst[++idx]=q2[i]; } sort(lst+1,lst+1+idx); idx=unique(lst+1,lst+1+idx)-lst-1; build(root[0],1,idx); for (int i=1;i<=n;i++) root[i]=root[0]; for (int i=1;i<=n;i++) add(i,getpos(a[i]),1); for (int i=1;i<=m;i++) if (qtype[i]) printf("%d\n",query(q1[i]-1,q2[i],q3[i])); else { add(q1[i],getpos(a[q1[i]]),-1); a[q1[i]]=q2[i]; add(q1[i],getpos(a[q1[i]]),1); } return 0; }