高级数据结构(树状数组套主席树):ZOJ 2112 Dynamic Rankings

Dynamic Rankings

Time Limit: 10 Seconds      Memory Limit: 32768 KB

The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They have developed a more powerful system such that for N numbers a[1], a[2], ..., a[N], you can ask it like: what is the k-th smallest number of a[i], a[i+1], ..., a[j]? (For some i<=j, 0<k<=j+1-i that you have given to it). More powerful, you can even change the value of some a[i], and continue to query, all the same.

Your task is to write a program for this computer, which

- Reads N numbers from the input (1 <= N <= 50,000)

- Processes M instructions of the input (1 <= M <= 10,000). These instructions include querying the k-th smallest number of a[i], a[i+1], ..., a[j] and change some a[i] to t.


Input

The first line of the input is a single number X (0 < X <= 4), the number of the test cases of the input. Then X blocks each represent a single test case.

The first line of each block contains two integers N and M, representing N numbers and M instruction. It is followed by N lines. The (i+1)-th line represents the number a[i]. Then M lines that is in the following format

Q i j k or
C i t

It represents to query the k-th number of a[i], a[i+1], ..., a[j] and change some a[i] to t, respectively. It is guaranteed that at any time of the operation. Any number a[i] is a non-negative integer that is less than 1,000,000,000.

There're NO breakline between two continuous test cases.


Output

For each querying operation, output one integer to represent the result. (i.e. the k-th smallest number of a[i], a[i+1],..., a[j])

There're NO breakline between two continuous test cases.


Sample Input

2
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3


Sample Output

3
6
3
6

  不知道为何,ZOJ上交这道题要FQ,BZOJ上有这道题,还TM是权限题,估计是偷的(鄙视BZOJ)。

  因为有修改操作,考虑保持原有的主席树结构,假设i位置上的数变化,那么要修改主席树中i及i以后的位置,如果一个一个修改肯定超时,可以考虑将修改的时间摊到查询上去,用Bit维护修改操作,记为前缀和,很好脑补。

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <algorithm>
  5 using namespace std;
  6 const int maxn=60010;
  7 const int maxm=2500010;
  8 int tot,cnt,hash[maxn],a[maxn];
  9 int sum[maxm],ch[maxm][2],rt[maxn],bit[maxn];
 10 int use[maxn],n;
 11 struct Ask{
 12     int l,r,k;
 13 }q[maxn];
 14 
 15 void Insert(int pre,int &rt,int l,int r,int g,int d){
 16     rt=++cnt;
 17     ch[rt][0]=ch[pre][0];
 18     ch[rt][1]=ch[pre][1];
 19     sum[rt]=sum[pre]+d;
 20     if(l==r)return;
 21     int mid=(l+r)>>1;
 22     if(mid>=g)Insert(ch[pre][0],ch[rt][0],l,mid,g,d);
 23     else Insert(ch[pre][1],ch[rt][1],mid+1,r,g,d);
 24 }
 25 
 26 void Modify(int p,int g,int d){
 27     while(p<=n){
 28         Insert(bit[p],bit[p],1,tot,g,d);
 29         p+=p&(-p);
 30     }
 31 }
 32 
 33 int Query(int pre,int rt,int l,int r,int k,int L,int R){
 34     if(l==r)return l;
 35     int mid=(l+r)>>1,p=R,c=0;
 36     while(p){c+=sum[ch[use[p]][0]];p-=p&(-p);}p=L-1;
 37     while(p){c-=sum[ch[use[p]][0]];p-=p&(-p);}
 38     c+=sum[ch[rt][0]]-sum[ch[pre][0]];
 39     if(c>=k){
 40         p=R;
 41         while(p){use[p]=ch[use[p]][0];p-=p&(-p);}p=L-1;
 42         while(p){use[p]=ch[use[p]][0];p-=p&(-p);}
 43         return Query(ch[pre][0],ch[rt][0],l,mid,k,L,R);
 44     }
 45     else{
 46         k-=c;p=R;
 47         while(p){use[p]=ch[use[p]][1];p-=p&(-p);}p=L-1;
 48         while(p){use[p]=ch[use[p]][1];p-=p&(-p);}
 49         return Query(ch[pre][1],ch[rt][1],mid+1,r,k,L,R);
 50     }
 51     
 52 }
 53 
 54 int Solve(int l,int r,int k){
 55     int p=l-1;
 56     while(p){use[p]=bit[p];p-=p&(-p);}p=r;
 57     while(p){use[p]=bit[p];p-=p&(-p);}
 58     return Query(rt[l-1],rt[r],1,tot,k,l,r);
 59 }
 60 
 61 void Init(){
 62     memset(rt,0,sizeof(rt));cnt=0;
 63     memset(bit,0,sizeof(bit));
 64 }
 65 
 66 bool cmp(int a,int b){
 67     return a>b;
 68 }
 69 char op[5]; 
 70 int main(){
 71     int T,Q;
 72     scanf("%d",&T);
 73     while(T--){
 74         Init();
 75         scanf("%d%d",&n,&Q);
 76         for(int i=1;i<=n;i++)
 77             scanf("%d",&a[i]);
 78         tot=n;
 79         for(int i=1;i<=Q;i++){
 80             scanf("%s",op);
 81             if(op[0]=='Q')
 82                 scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);
 83             else{
 84                 scanf("%d%d",&q[i].l,&q[i].k);
 85                 a[++tot]=q[i].k;q[i].r=-1;
 86             }
 87         }        
 88         for(int i=1;i<=tot;i++)
 89             hash[i]=a[i];
 90         sort(hash+1,hash+tot+1);
 91         for(int i=1;i<=tot;i++)
 92             a[i]=lower_bound(hash+1,hash+tot+1,a[i])-hash;    
 93 
 94         for(int i=1;i<=n;i++)
 95             Insert(rt[i-1],rt[i],1,tot,a[i],1);
 96         for(int i=1,head=n;i<=Q;i++){
 97             if(q[i].r==-1){
 98                 Modify(q[i].l,a[q[i].l],-1);
 99                 Modify(q[i].l,a[++head],1);
100                 a[q[i].l]=a[head];
101             }
102             else
103                 printf("%d\n",hash[Solve(q[i].l,q[i].r,q[i].k)]);
104         }
105     }
106     return 0;
107 }

2016年6月9日重打了一遍……

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdio>
 5 using namespace std;
 6 const int maxn=60010;
 7 const int maxm=2500010;
 8 char op[10];
 9 int n,Q,T,use[maxn];
10 int qa[maxn],qb[maxn],qk[maxn];
11 int tot,cnt,ch[maxm][2],sum[maxm];
12 int a[maxn],hash[maxn],bit[maxn],rt[maxn];
13 void Insert(int pre,int &rt,int l,int r,int g,int d){
14     rt=++cnt;
15     ch[rt][0]=ch[pre][0];
16     ch[rt][1]=ch[pre][1];
17     sum[rt]=sum[pre]+d;
18     if(l==r)return;
19     if(l+r>>1>=g)Insert(ch[pre][0],ch[rt][0],l,l+r>>1,g,d);
20     else Insert(ch[pre][1],ch[rt][1],(l+r>>1)+1,r,g,d);
21 }
22 void Modify(int p,int g,int d){
23     while(p<=n){
24         Insert(bit[p],bit[p],1,tot,g,d);
25         p+=p&(-p);
26     }
27 }
28 int Query(int pre,int rt,int l,int r,int k,int L,int R){
29     if(l==r)return l;
30     int c=sum[ch[rt][0]]-sum[ch[pre][0]],p=R;
31     while(p){c+=sum[ch[use[p]][0]];p-=p&(-p);}p=L-1;
32     while(p){c-=sum[ch[use[p]][0]];p-=p&(-p);}
33     if(c>=k){p=R;
34         while(p){use[p]=ch[use[p]][0];p-=p&(-p);}p=L-1;
35         while(p){use[p]=ch[use[p]][0];p-=p&(-p);}
36         return Query(ch[pre][0],ch[rt][0],l,l+r>>1,k,L,R);
37     }
38     else{p=R;
39         while(p){use[p]=ch[use[p]][1];p-=p&(-p);}p=L-1;
40         while(p){use[p]=ch[use[p]][1];p-=p&(-p);}
41         return Query(ch[pre][1],ch[rt][1],(l+r>>1)+1,r,k-c,L,R);
42     }
43 }    
44 int Solve(int i){
45     int p=qb[i];
46     while(p){use[p]=bit[p];p-=p&(-p);}p=qa[i]-1;
47     while(p){use[p]=bit[p];p-=p&(-p);}
48     return Query(rt[qa[i]-1],rt[qb[i]],1,tot,qk[i],qa[i],qb[i]);
49 }
50 void Init(){
51     memset(bit,0,sizeof(bit));
52     cnt=0;tot=n;
53 }
54 int main(){
55 #ifndef ONLINE_JUDGE
56     freopen("dynrank.in","r",stdin);
57     freopen("dynrank.out","w",stdout);
58 #endif
59     scanf("%d",&T);
60     while(T--){
61         scanf("%d%d",&n,&Q);Init();
62         for(int i=1;i<=n;i++){
63             scanf("%d",&a[i]);
64             hash[i]=a[i];
65         }
66         for(int i=1;i<=Q;i++){
67             scanf("%s",op);
68             if(op[0]=='Q')scanf("%d%d%d",&qa[i],&qb[i],&qk[i]);
69             else{
70                 scanf("%d%d",&qa[i],&qk[i]);
71                 tot++;hash[tot]=a[tot]=qk[i];qb[i]=-1;
72             }
73         }
74         sort(hash+1,hash+tot+1);
75         for(int i=1;i<=tot;i++)
76             a[i]=lower_bound(hash+1,hash+tot+1,a[i])-hash;    
77         for(int i=1;i<=n;i++)Insert(rt[i-1],rt[i],1,tot,a[i],1);
78         for(int i=1,p=n;i<=Q;i++){
79             if(qb[i]==-1){
80                 Modify(qa[i],a[qa[i]],-1);
81                 Modify(qa[i],a[++p],1);
82                 a[qa[i]]=a[p];
83             }
84             else
85                 printf("%d\n",hash[Solve(i)]);
86         }
87     }
88     return 0;
89 }

   还打了一个强大的整体二分。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 const int maxn=200010;
 6 int T,n,Q,cntQ;
 7 int num[maxn],ans[maxn],bit[maxn];
 8 char op[10];
 9 struct Node{
10     int x,y,k,id,tp;
11 }a[maxn],t1[maxn],t2[maxn];
12 //tp==1 add; tp==2 del; tp==3 query;
13 
14 void Add(int x,int d){
15     while(x<=n){
16         bit[x]+=d;
17         x+=x&(-x);
18     }
19 }
20 
21 int Query(int x){
22     int ret=0;
23     while(x){
24         ret+=bit[x];
25         x-=x&(-x);
26     }
27     return ret;
28 }
29 
30 void Solve(int h,int t,int l,int r){
31     if(l==r){
32         for(int i=h;i<=t;i++)
33             if(a[i].tp==3)ans[a[i].id]=l;
34         return;
35     }
36     if(h>t)return;
37     int p1=0,p2=0,d;
38     for(int i=h;i<=t;i++){
39         if(a[i].tp==3){
40             d=Query(a[i].y)-Query(a[i].x-1);
41             if(d>=a[i].k)t1[++p1]=a[i];
42             else{
43                 a[i].k-=d;
44                 t2[++p2]=a[i];
45             }
46         }
47         else if(a[i].k<=l+r>>1){
48             if(a[i].tp==1)Add(a[i].x,1);
49             if(a[i].tp==2)Add(a[i].x,-1);
50             t1[++p1]=a[i];
51         }
52         else t2[++p2]=a[i];
53     }
54     for(int i=h;i<=t;i++){
55         if(a[i].k<=l+r>>1){
56             if(a[i].tp==1)Add(a[i].x,-1);
57             if(a[i].tp==2)Add(a[i].x,1);
58         }
59     }
60     for(int i=1;i<=p1;i++)a[h+i-1]=t1[i];
61     for(int i=1;i<=p2;i++)a[h+i+p1-1]=t2[i];
62     Solve(h,h+p1-1,l,l+r>>1);
63     Solve(h+p1,t,(l+r>>1)+1,r);
64 }
65 
66 int main(){
67 #ifndef ONLINE_JUDGE
68     freopen("dynrank.in","r",stdin);
69     freopen("dynrank.out","w",stdout);
70 #endif
71     scanf("%d",&T);
72     while(T--){
73         scanf("%d%d",&n,&Q);
74         for(int i=1;i<=n;i++){
75             scanf("%d",&a[i].k);
76             a[i].x=i;a[i].tp=1;
77             num[i]=a[i].k;
78         }
79         cntQ=0;
80         int x,y,k;
81         while(Q--){
82             scanf("%s",op);
83             if(op[0]=='Q'){
84                 scanf("%d%d%d",&x,&y,&k);
85                 a[++n].id=++cntQ;a[n].tp=3;
86                 a[n].x=x;a[n].y=y;a[n].k=k;
87             }
88             else{
89                 scanf("%d%d",&x,&k);
90                 a[++n].tp=2;a[n].x=x;a[n].k=num[x];
91                 a[++n].tp=1;a[n].x=x;a[n].k=k;num[x]=k;
92             }
93         }
94         Solve(1,n,1,1000000000);
95         for(int i=1;i<=cntQ;i++)
96             printf("%d\n",ans[i]);            
97     }
98     return 0;    
99 }

 

posted @ 2016-04-10 20:21  TenderRun  阅读(242)  评论(0编辑  收藏  举报