【BOZJ 1901】Zju2112 Dynamic Rankings

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

Sample Output

3
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\n",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\n",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\n",ans[i]);
67 } 

这就是时间差距。。。

posted @ 2016-03-01 08:17  Alisahhh  阅读(265)  评论(0编辑  收藏  举报