[BZOJ3196]二逼平衡树
Description
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)
Input
第一行两个数 n,m 表示长度为n的有序序列和m个操作
第二行有n个数,表示有序序列
下面有m行,opt表示操作标号
若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继
Output
对于操作1,2,4,5各输出一行,表示查询结果
Sample Input
9 6
4 2 2 1 9 4 0 1 1
2 1 4 3
3 4 10
2 1 4 3
1 2 5 9
4 3 9 5
5 2 8 5
4 2 2 1 9 4 0 1 1
2 1 4 3
3 4 10
2 1 4 3
1 2 5 9
4 3 9 5
5 2 8 5
Sample Output
2
4
3
4
9
4
3
4
9
树状数组套线段树,PS:yyb的代码真好看
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define M 100010 6 #define ls ch[node][0] 7 #define rs ch[node][1] 8 using namespace std; 9 int read() { 10 char ch=getchar();int x=0,f=1; 11 while(ch>'9'||ch<'0') {if(ch=='-')f=-1;ch=getchar();} 12 while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); 13 return x*f; 14 } 15 int n,m,cnt,tot,tx,ty; 16 int rt[M],a[M],b[M],qx[M],qy[M],opt[M],ql[M],qr[M],qk[M]; 17 int val[M<<6],ch[M<<6][2]; 18 void insert(int &node,int l,int r,int x,int v) { 19 if(!node) node=++cnt;val[node]+=v; 20 if(l==r) return; 21 int mid=(l+r)>>1; 22 if(x<=mid) insert(ls,l,mid,x,v); 23 else insert(rs,mid+1,r,x,v); 24 } 25 int query(int node,int l,int r,int x) { 26 if(l==r) return val[node]; 27 int mid=(l+r)>>1; 28 if(x<=mid) return query(ls,l,mid,x); 29 else return val[ls]+query(rs,mid+1,r,x); 30 } 31 void change(int loc,int v) { 32 for(int i=loc;i<=n;i+=(i&-i)) 33 insert(rt[i],1,tot,a[loc],v); 34 } 35 int Rank(int l,int r,int k) { 36 int ans=0; 37 for(int i=l-1;i;i-=(i&-i)) ans-=query(rt[i],1,tot,k); 38 for(int i=r;i;i-=(i&-i)) ans+=query(rt[i],1,tot,k); 39 return ans; 40 } 41 int findx(int l,int r,int k) { 42 if(l==r) return l; 43 int sum=0,mid=(l+r)>>1; 44 for(int i=1;i<=tx;i++) sum-=val[ch[qx[i]][0]]; 45 for(int i=1;i<=ty;i++) sum+=val[ch[qy[i]][0]]; 46 if(k<=sum) { 47 for(int i=1;i<=tx;i++) qx[i]=ch[qx[i]][0]; 48 for(int i=1;i<=ty;i++) qy[i]=ch[qy[i]][0]; 49 return findx(l,mid,k); 50 } 51 else{ 52 for(int i=1;i<=tx;i++) qx[i]=ch[qx[i]][1]; 53 for(int i=1;i<=ty;i++) qy[i]=ch[qy[i]][1]; 54 return findx(mid+1,r,k-sum); 55 } 56 } 57 int kth(int l,int r,int k) { 58 tx=ty=0; 59 for(int i=l-1;i;i-=(i&-i)) qx[++tx]=rt[i]; 60 for(int i=r;i;i-=(i&-i)) qy[++ty]=rt[i]; 61 return b[findx(1,tot,k)]; 62 } 63 int main() { 64 n=read();m=read(); 65 for(int i=1;i<=n;i++) a[i]=b[++tot]=read(); 66 for(int i=1;i<=m;i++) { 67 opt[i]=read(); 68 if(opt[i]!=3) { 69 ql[i]=read(),qr[i]=read(),qk[i]=read(); 70 if(opt[i]!=2) b[++tot]=qk[i]; 71 } 72 else{ 73 ql[i]=read(),qr[i]=read(); 74 b[++tot]=qr[i]; 75 } 76 } 77 sort(b+1,b+1+tot); 78 tot=unique(b+1,b+1+tot)-b-1; 79 for(int i=1;i<=n;i++) { 80 a[i]=lower_bound(b+1,b+1+tot,a[i])-b; 81 change(i,1); 82 } 83 for(int i=1;i<=m;i++) { 84 if(opt[i]==1) { 85 int k=lower_bound(b+1,b+1+tot,qk[i])-b; 86 printf("%d\n",Rank(ql[i],qr[i],k-1)+1); 87 } 88 if(opt[i]==2) printf("%d\n",kth(ql[i],qr[i],qk[i])); 89 if(opt[i]==3) { 90 change(ql[i],-1); 91 a[ql[i]]=lower_bound(b+1,b+1+tot,qr[i])-b; 92 change(ql[i],1); 93 } 94 if(opt[i]==4) { 95 int x=lower_bound(b+1,b+1+tot,qk[i])-b; 96 int k=Rank(ql[i],qr[i],x-1); 97 printf("%d\n",kth(ql[i],qr[i],k)); 98 } 99 if(opt[i]==5) { 100 int x=lower_bound(b+1,b+1+tot,qk[i])-b; 101 int k=Rank(ql[i],qr[i],x); 102 printf("%d\n",kth(ql[i],qr[i],k+1)); 103 } 104 } 105 return 0; 106 }