[BZOJ 1901]Dynamic Rankings
[BZOJ 1901]Dynamic Rankings
题目
给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改变后的a继续回答上面的问题。INPUT
第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。分别表示序列的长度和指令的个数。第二行有n个数,表示a[1],a[2]……a[n],这些数都小于10^9。接下来的m行描述每条指令每行的格式是下面两种格式中的一种。Q i j k 或者 C i tQ i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为tm,n≤10000OUTPUT
对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行
SAMPLE
INPUT
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3OUTPUT
3
6
解题报告
打了一下午的静态主席树,终于进阶到动态的了= =
树状数组套一个主席树
我们想,主席树是通过前缀和来维护信息的,我们一修改就全都乱了,所以我们需要一个数据结构来维护前缀和,很自然的就想到了树状数组
我们在修改时,利用树状数组,将其原来所产生的影响清除,然后进行更新,就可以对主席树进行动态操作了
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 inline int read(){ 7 int sum(0); 8 char ch(getchar()); 9 for(;ch<'0'||ch>'9';ch=getchar()); 10 for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar()); 11 return sum; 12 } 13 int n,m; 14 int tot,size,cnt; 15 int v[10005],num[20005],has[20005]; 16 int rt[10005],sum[2500005],lch[2500005],rch[2500005]; 17 int A[10005],B[10005],K[10005]; 18 bool flag[10005]; 19 int a,b,L[30],R[30]; 20 char op[2]; 21 inline int lowbit(int x){ 22 return x&-x; 23 } 24 inline int find(int x){ 25 int l(1),r(size),mid; 26 while(l<=r){ 27 mid=(l+r)>>1; 28 if(has[mid]<x) 29 l=mid+1; 30 else 31 r=mid-1; 32 } 33 return l; 34 //return lower_bound(has+1,has+size+1,x)-has; 35 } 36 inline void update(int &x,int las,int pos,int w,int l,int r){ 37 x=++cnt; 38 lch[x]=lch[las]; 39 rch[x]=rch[las]; 40 sum[x]=sum[las]+w; 41 if(l==r) 42 return; 43 int mid((l+r)>>1); 44 if(pos<=mid) 45 update(lch[x],lch[las],pos,w,l,mid); 46 else 47 update(rch[x],rch[las],pos,w,mid+1,r); 48 } 49 inline int query(int l,int r,int k){ 50 if(l==r) 51 return l; 52 int suml(0),sumr(0),mid((l+r)>>1); 53 for(int i=1;i<=a;++i)suml+=sum[lch[L[i]]]; 54 for(int i=1;i<=b;++i)sumr+=sum[lch[R[i]]]; 55 if(sumr-suml>=k){ 56 for(int i=1;i<=a;++i)L[i]=lch[L[i]]; 57 for(int i=1;i<=b;++i)R[i]=lch[R[i]]; 58 return query(l,mid,k); 59 } 60 else{ 61 for(int i=1;i<=a;++i)L[i]=rch[L[i]]; 62 for(int i=1;i<=b;++i)R[i]=rch[R[i]]; 63 return query(mid+1,r,k-(sumr-suml)); 64 } 65 } 66 int main(){ 67 n=read(),m=read(); 68 for(int i=1;i<=n;++i){ 69 v[i]=read(); 70 num[++tot]=v[i]; 71 } 72 for(int i=1;i<=m;++i){ 73 scanf("%s",op); 74 if(op[0]=='Q'){ 75 flag[i]=1; 76 A[i]=read(); 77 B[i]=read(); 78 K[i]=read(); 79 } 80 else{ 81 A[i]=read(); 82 B[i]=read(); 83 num[++tot]=B[i]; 84 } 85 } 86 sort(num+1,num+tot+1); 87 has[++size]=num[1]; 88 for(int i=2;i<=tot;++i) 89 if(num[i]!=num[i-1]) 90 has[++size]=num[i]; 91 for(int i=1;i<=n;++i){ 92 int tmp(find(v[i])); 93 for(int j=i;j<=n;j+=lowbit(j)) 94 update(rt[j],rt[j],tmp,1,1,size); 95 } 96 for(int i=1;i<=m;++i){ 97 if(flag[i]){ 98 a=b=0; 99 --A[i]; 100 for(int j=A[i];j>0;j-=lowbit(j)) 101 L[++a]=rt[j]; 102 for(int j=B[i];j>0;j-=lowbit(j)) 103 R[++b]=rt[j]; 104 printf("%d\n",has[query(1,size,K[i])]); 105 } 106 else{ 107 int tmp(find(v[A[i]])); 108 for(int j=A[i];j<=n;j+=lowbit(j)) 109 update(rt[j],rt[j],tmp,-1,1,size); 110 v[A[i]]=B[i]; 111 tmp=find(B[i]); 112 for(int j=A[i];j<=n;j+=lowbit(j)) 113 update(rt[j],rt[j],tmp,1,1,size); 114 } 115 } 116 }