Description
给定一个含有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继续回答上面的问题。你需要编一个这样的程序,从输入文件中读入序列a,然后读入一系列的指令,包括询问指令和修改指令。对于每一个询问指令,你必须输出正确的回答。 第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。分别表示序列的长度和指令的个数。第二行有n个数,表示a[1],a[2]……a[n],这些数都小于10^9。接下来的m行描述每条指令,每行的格式是下面两种格式中的一种。 Q i j k 或者 C i t Q 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]改变成为t。
Input
对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。
Output
Sample Input
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
Sample Output
3
6
6
HINT
20%的数据中,m,n≤100; 40%的数据中,m,n≤1000; 100%的数据中,m,n≤10000。
树套树
1 #include<cstdio> 2 #include<cstdlib> 3 using namespace std; 4 const int N=3000001,inf=1000000000; 5 struct tree{int lch,rch,num,sz,w,rnd;}tr[N]; 6 int a[10010],n,m,sz,root[10010*4]; 7 void updata(int x){ 8 int l=tr[x].lch,r=tr[x].rch; 9 tr[x].sz=tr[l].sz+tr[r].sz+tr[x].w; 10 } 11 12 void lturn(int &k) 13 {int t=tr[k].rch;tr[k].rch=tr[t].lch;tr[t].lch=k;updata(k);updata(t);k=t;} 14 void rturn(int &k) 15 {int t=tr[k].lch;tr[k].lch=tr[t].rch;tr[t].rch=k;updata(k);updata(t);k=t;} 16 void ins(int &k,int x){ 17 if(!k){ 18 k=++sz;tr[k].rnd=rand();tr[k].sz=1;tr[k].num=x;tr[k].w=1;return; 19 } 20 if(tr[k].num==x) tr[k].w++; 21 else if(tr[k].num>x) { 22 ins(tr[k].lch,x); 23 if(tr[k].rnd>tr[tr[k].lch].rnd) rturn(k); 24 }else{ 25 ins(tr[k].rch,x); 26 if(tr[k].rnd>tr[tr[k].rch].rnd) lturn(k); 27 } 28 updata(k); 29 } 30 31 void insert(int k,int l,int r,int x,int y){ 32 if(l<=y&&r>=y) ins(root[k],x); 33 if(l==r) return; 34 int mid=(l+r)>>1; 35 if(y>mid) insert(k<<1|1,mid+1,r,x,y); 36 else insert(k<<1,l,mid,x,y); 37 } 38 39 int find(int k,int x){ 40 if(!k) return 0; 41 int l=tr[k].lch,r=tr[k].rch; 42 if(tr[k].num>x) return find(l,x); 43 else if(tr[k].num<x) return find(r,x)+tr[l].sz+tr[k].w; 44 else return tr[l].sz; 45 } 46 47 int get_rank(int k,int l,int r,int L,int R,int x){ 48 int mid=(l+r)>>1; 49 if(l==L&&r==R) return find(root[k],x); 50 if(R<=mid) return get_rank(k<<1,l,mid,L,R,x); 51 else if(L>mid) return get_rank(k<<1|1,mid+1,r,L,R,x); 52 else return get_rank(k<<1,l,mid,L,mid,x)+get_rank(k<<1|1,mid+1,r,mid+1,R,x); 53 } 54 55 int ask(int x,int y,int rk){ 56 int l=1,r=inf,mid=(l+r)>>1,ans=0; 57 while(l<=r){ 58 mid=(l+r)>>1; 59 int k=get_rank(1,1,n,x,y,mid); 60 if(k<=rk) ans=mid,l=mid+1; 61 else r=mid-1; 62 } 63 return ans; 64 } 65 66 void del(int &k,int p){ 67 if(tr[k].num==p){ 68 if(tr[k].w>1) tr[k].w--,tr[k].sz--; 69 else{ 70 if(tr[k].lch*tr[k].rch==0) k=tr[k].lch+tr[k].rch; 71 else if(tr[tr[k].lch].rnd<tr[tr[k].rch].rnd) rturn(k),del(k,p); 72 else lturn(k),del(k,p); 73 } 74 } 75 else{ 76 tr[k].sz--; 77 if(tr[k].num>p) del(tr[k].lch,p);else del(tr[k].rch,p); 78 } 79 } 80 81 void make(int &rt,int p,int t){ 82 ins(rt,t); 83 del(rt,p); 84 } 85 86 void change(int k,int l,int r,int x,int p,int t){ 87 if(l<=x&&r>=x) make(root[k],p,t); 88 if(l==r) return; 89 int mid=(l+r)>>1; 90 if(x<=mid) change(k<<1,l,mid,x,p,t); 91 else change(k<<1|1,mid+1,r,x,p,t); 92 } 93 94 int main(){ 95 scanf("%d%d",&n,&m); 96 for(int i=1;i<=n;i++){ 97 scanf("%d",&a[i]); 98 insert(1,1,n,a[i],i); 99 } 100 char s[4]; 101 for(int i=1;i<=m;i++){ 102 scanf("%s",s); 103 if(s[0]=='Q') { 104 int l,r,rk; 105 scanf("%d%d%d",&l,&r,&rk); 106 printf("%d ",ask(l,r,rk-1)); 107 }else{ 108 int x,t; 109 scanf("%d%d",&x,&t); 110 change(1,1,n,x,a[x],t); 111 a[x]=t; 112 } 113 } 114 }
树状数组+主席树
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #define N 2200001 5 using namespace std; 6 int n,m,tot,top,cnt; 7 int v[10001],num[20001]; 8 int A[10001],B[10001],X[10001],root[10001],K[10001]; 9 int sz[N],ls[N],rs[N]; 10 int L[30],R[30],a,b; 11 int lowbit(int x){return x&(-x);} 12 void updata(int last,int l,int r,int &k,int x,int add){ 13 k=++cnt; 14 int mid=(l+r)>>1; 15 sz[k]=sz[last]+add;ls[k]=ls[last];rs[k]=rs[last]; 16 if(l==r) return; 17 if(x<=mid) updata(ls[last],l,mid,ls[k],x,add); 18 else updata(rs[last],mid+1,r,rs[k],x,add); 19 } 20 21 int query(int l,int r,int k){ 22 if(l==r) return l; 23 int mid=(l+r)>>1; 24 int suml=0,sumr=0; 25 for(int i=1;i<=a;i++)suml+=sz[ls[L[i]]]; 26 for(int i=1;i<=b;i++)sumr+=sz[ls[R[i]]]; 27 if(sumr-suml>=k){ 28 for(int i=1;i<=a;i++) L[i]=ls[L[i]]; 29 for(int i=1;i<=b;i++) R[i]=ls[R[i]]; 30 return query(l,mid,k); 31 }else{ 32 for(int i=1;i<=a;i++) L[i]=rs[L[i]]; 33 for(int i=1;i<=b;i++) R[i]=rs[R[i]]; 34 return query(mid+1,r,k-(sumr-suml)); 35 } 36 } 37 38 int main(){ 39 scanf("%d%d",&n,&m); 40 for(int i=1;i<=n;i++){ 41 scanf("%d",&v[i]); 42 num[++top]=v[i]; 43 } 44 char opt[4]; 45 for(int i=1;i<=m;i++){ 46 scanf("%s%d%d",opt,&A[i],&B[i]); 47 if(opt[0]=='Q') scanf("%d",&X[i]),K[i]=1; 48 else num[++top]=B[i]; 49 } 50 sort(num+1,num+top+1); 51 tot=unique(num+1,num+top+1)-num-1; 52 for(int i=1;i<=n;i++){ 53 int t=lower_bound(num+1,num+tot+1,v[i])-num; 54 for(int j=i;j<=n;j+=lowbit(j)) 55 updata(root[j],1,tot,root[j],t,1); 56 } 57 for(int i=1;i<=m;i++){ 58 if(K[i]){ 59 a=0,b=0;A[i]--; 60 for(int j=A[i];j>=1;j-=lowbit(j)) L[++a]=root[j]; 61 for(int j=B[i];j>=1;j-=lowbit(j)) R[++b]=root[j]; 62 printf("%d ",num[query(1,tot,X[i])]); 63 }else{ 64 int t=lower_bound(num+1,num+tot+1,v[A[i]])-num; 65 for(int j=A[i];j<=n;j+=lowbit(j)) 66 updata(root[j],1,tot,root[j],t,-1); 67 v[A[i]]=B[i]; 68 t=lower_bound(num+1,num+tot+1,v[A[i]])-num; 69 for(int j=A[i];j<=n;j+=lowbit(j)) 70 updata(root[j],1,tot,root[j],t,1); 71 } 72 } 73 }
整体二分
1 #include<cstdio> 2 const int inf=1000000000; 3 struct node{int flag,x,y,no,rk,cur;}p[300100],p1[300100],p2[300010]; 4 int n,m,a[100010],cnt,sum,ans[100100],w[300010],tmp[300010],num; 5 6 void add(int x,int y){ 7 for(int i=x;i<=n;i+=(i&(-i))) w[i]+=y; 8 } 9 10 int query(int x){ 11 int ans=0; 12 for (int i=x;i>0;i-=(i&(-i))) ans+=w[i]; 13 return ans; 14 } 15 16 void divid(int h,int t,int l,int r){ 17 if(h>t) return; 18 if(l==r) {for(int i=h;i<=t;i++) 19 ans[p[i].no]=l;return;} 20 int mid=(l+r)>>1; 21 for(int i=h;i<=t;i++){ 22 if(p[i].flag==1&&p[i].y<=mid) add(p[i].x,1); 23 else if(p[i].flag==2&&p[i].y<=mid) add(p[i].x,-1); 24 else if(p[i].flag==3)tmp[i]=query(p[i].y)-query(p[i].x-1); 25 } 26 for(int i=h;i<=t;i++){ 27 if(p[i].flag==1&&p[i].y<=mid) add(p[i].x,-1); 28 else if(p[i].flag==2&&p[i].y<=mid) add(p[i].x,1); 29 } 30 int l1=0,l2=0; 31 for(int i=h;i<=t;i++){ 32 if(p[i].flag==3){ 33 if(tmp[i]+p[i].cur>p[i].rk-1) p1[++l1]=p[i]; 34 else p[i].cur+=tmp[i],p2[++l2]=p[i]; 35 } 36 else { 37 if(p[i].y<=mid) p1[++l1]=p[i];else p2[++l2]=p[i]; 38 } 39 } 40 for(int i=h;i<=l1+h-1;i++) p[i]=p1[i-h+1]; 41 for(int i=l1+h;i<=t;i++) p[i]=p2[i-l1-h+1]; 42 divid(h,l1+h-1,l,mid); 43 divid(l1+h,t,mid+1,r); 44 } 45 46 int main(){ 47 scanf("%d%d",&n,&m); 48 for(int i=1;i<=n;i++){ 49 scanf("%d",&a[i]); 50 p[++cnt].flag=1;p[cnt].x=i;p[cnt].y=a[i]; 51 } 52 for(int i=1;i<=m;i++){ 53 char opt[4];int x,y,k; 54 scanf("%s%d%d",opt,&x,&y); 55 if(opt[0]=='Q'){ 56 scanf("%d",&k); 57 p[++cnt].x=x,p[cnt].y=y;p[cnt].flag=3;p[cnt].no=++num; 58 p[cnt].rk=k; 59 }else{ 60 p[++cnt].x=x;p[cnt].y=a[x];p[cnt].flag=2; 61 a[x]=y; 62 p[++cnt].x=x;p[cnt].y=a[x];p[cnt].flag=1; 63 } 64 } 65 divid(1,cnt,0,inf); 66 for(int i=1;i<=num;i++) printf("%d ",ans[i]); 67 }
这就是时间差距。。。