# zoj 2112 or bzoj1901 分析动态区间第k大的几种解法。

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.

- 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.

<b< dd="">

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.

<b< dd="">

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

<b< dd="">

Sample Output

3
6
3
6

 1 #include<bits/stdc++.h>
2 using namespace std;
3 int const N=50000+10;
4 int const sz=600;
5 #define st(x) ((x-1)*sz+1)
6 #define ed(x) min(n,(x*sz))
7 #define bl(x) (x-1)/sz+1
8 int n,m,a[N],num,b[2003],ta[N];
9 int query(int x,int y,int z){
10     int t1=bl(x);
11     int t2=bl(y);
12     int l=0,r=1e9;
13     while (l<r){
14         int mid=(l+r)/2;
15         int cnt=0;
16         if(t1==t2){
17             for(int i=x;i<=y;i++)
18                 if(ta[i]<=mid) cnt++;
19         }else {
20             for(int i=x;i<=ed(t1);i++)
21                 if(ta[i]<=mid) cnt++;
22             for(int i=st(t2);i<=y;i++)
23                 if(ta[i]<=mid) cnt++;
24             for(int i=t1+1;i<=t2-1;i++){
25                 int s=st(i);
26                 int t=ed(i);
27                 if(a[t]<=mid) cnt+=t-s+1;
28                 else cnt+=upper_bound(a+s,a+t+1,mid)-(a+s);
29             }
30         }
31         if(cnt>=z) r=mid;
32         else l=mid+1;
33     }
34     return l;
35 }
36 void modify(int x,int y){
37     int t=bl(x);
38     b[0]=0;
39     int v=ta[x],cnt=1;
40     ta[x]=y;
41     for(int i=st(t);i<=ed(t);i++)
42         if(a[i]!=v  || !cnt) b[++b[0]]=a[i];
43         else cnt--;
44     int k=ed(t)-st(t);
45     while (k && b[k]>y){
46         b[k+1]=b[k];
47         k--;
48     }
49     b[k+1]=y;
50     int tot=ed(t)-st(t)+1;
51     for(int i=1;i<=tot;i++)
52         a[st(t)+i-1]=b[i];
53 }
54 int main(){
55     int cas;
56     scanf("%d",&cas);
57     while (cas--){
58         scanf("%d%d",&n,&m);
59         for(int i=1;i<=n;i++)
60             scanf("%d",&a[i]),ta[i]=a[i];
61         num=(n-1)/sz+1;
62         for(int i=1;i<=num;i++){
63             int x=st(i);
64             int y=ed(i);
65             sort(a+x,a+y+1);
66         }
67         while (m--){
68             char s[2];
69             int x,y,z;
70             scanf("%s%d%d",s,&x,&y);
71             if(s[0]=='C'){
72                 modify(x,y);
73             }else {
74                 scanf("%d",&z);
75                 printf("%d\n",query(x,y,z));
76             }
77         }
78     }
79     return 0;
80 }
View Code

方法二：

  1 #include<bits/stdc++.h>
2 using namespace std ;
3 int const N=60000+10;
4 int const M=1000000+10;
5 int n,m,r[N],sz[M],lc[M],rc[M],sum,val[M],tot[M],cnt[M],top,s[N],a[N];
6 void update(int x){
7     sz[x]=sz[lc[x]]+sz[rc[x]]+1;
8     tot[x]=cnt[x]+tot[lc[x]]+tot[rc[x]];
9 }
10 void dfs(int x){
11     if(!x) return;
12     dfs(lc[x]);
13     if(cnt[x]) s[++top]=x;
14     dfs(rc[x]);
15 }
16 int build(int l,int r){
17     if(l>r) return 0;
18     int x=s[(l+r)/2];
19     if(l==r){
20         sz[x]=1;tot[x]=cnt[x]; lc[x]=rc[x]=0;
21         return x;
22     }
23     int mid=(l+r)/2;
24     lc[x]=build(l,mid-1);
25     rc[x]=build(mid+1,r);
26     update(x);
27     return x;
28 }
29 void rebuild(int &x){
30     top=0;
31     dfs(x);
32     x=build(1,top);
33 }
34 void  ins(int &x,int v){
35     if(!x) {
36         x=++sum;sz[x]=1; lc[x]=rc[x]=0;val[x]=v; tot[x]=cnt[x]=1;
37         return;
38     }
39     if(val[x]==v) {
40         cnt[x]++;
41     }else {
42         if(v<val[x]) ins(lc[x],v);
43         else ins(rc[x],v);
44     }
45     update(x);
46     if(sz[x]*0.75<max(sz[lc[x]],sz[rc[x]])) rebuild(x);
47 }
48
49 void dl(int &x,int v){
50     if(val[x]==v) {
51         cnt[x]--;
52     }else if(v<val[x]) dl(lc[x],v);
53     else dl(rc[x],v);
54     update(x);
55 }
56 void  add(int x,int v){for(; x<=n; x+=x&-x)    ins(r[x],v);}
57 void  del(int x,int v){for(; x<=n; x+=x&-x)    dl(r[x],v);}
58 int count(int x,int mid){
59     if(!x) return 0;
60     int ret;
61     if(val[x]<=mid)  ret=tot[lc[x]]+cnt[x]+count(rc[x],mid);
62     else ret=count(lc[x],mid);
63     return ret;
64 }
65 int calc(int x,int mid){
66     int num=0;
67     for(; x; x-=x&-x) num+=count(r[x],mid);
68     return num;
69 }
70 int solve(int x,int y,int z){
71     int l=0,r=1e9;
72     while (l<r){
73         int mid=(l+r)/2;
74         int num=calc(y,mid)-calc(x-1,mid);
75         if(num>=z) r=mid;
76         else l=mid+1;
77     }
78     return r;
79 }
80 int main(){
81     int cas;
82     scanf("%d",&cas);
83     while (cas--){
84         scanf("%d%d",&n,&m);
85         sum=0;
86         memset(r,0,sizeof(r));
87         for(int i=1;i<=n;i++){
88             scanf("%d",&a[i]);
90         }
91         while (m--){
92             char s[2];
93             scanf("%s",s);
94             if(s[0]=='C'){
95                 int x,y;
96                 scanf("%d%d",&x,&y);
97               del(x,a[x]);
99             } else {
100                 int x,y,z;
101                 scanf("%d%d%d",&x,&y,&z);
102                 printf("%d\n",solve(x,y,z));
103             }
104         }
105     }
106     return 0;
107 }
View Code

方法三：

3.按值建线段树套平衡树 O(n*log^2n) 500ms

  1 #include<bits/stdc++.h>
2 using namespace std;
3 int const N=20000+10;
4 int const M=300000+10;
5 #define lc (x<<1)
6 #define rc (x<<1|1)
7 #define mid (l+r>>1)
8 struct query{
9     int k,x,y,z;
10 }q[N];
11 int n,m,a[N],b[N],sz[M],ls[M],rs[M],cnt[M],tot[M],sum,val[M],s[N],top,rt[N<<2];
12 void update(int x){
13     sz[x]=1+sz[ls[x]]+sz[rs[x]];
14     tot[x]=cnt[x]+tot[ls[x]]+tot[rs[x]];
15 }
16 void dfs(int x){
17     if(!x) return;
18     dfs(ls[x]) ;
19     if(cnt[x]) s[++top]=x;
20     dfs(rs[x]);
21 }
22 int build(int l,int r){
23     if(l>r) return 0;
24     int x=s[mid];
25     if(l==r){
26         sz[x]=1;tot[x]=cnt[x]; ls[x]=rs[x]=0;
27         return x;
28     }
29     ls[x]=build(l,mid-1);
30     rs[x]=build(mid+1,r);
31     update(x);
32     return x;
33 }
34
35 void rebuild(int &x){
36     top=0;
37     dfs(x);
38     x=build(1,top);
39 }
40 void ins(int &x,int v){
41     if(!x) {
42         x=++sum;sz[x]=cnt[x]=tot[x]=1; ls[x]=rs[x]=0; val[x]=v;
43         return;
44     }
45     if(val[x]==v)  cnt[x]++;
46     else if(v<val[x]) ins(ls[x],v);
47     else ins(rs[x],v);
48     update(x);
49     if(sz[x]*0.75<max(sz[ls[x]],sz[rs[x]]))
50         rebuild(x);
51 }
52 void insert(int x,int l,int r,int p,int v){
53     ins(rt[x],v);
54     if(l==r) return;
55     if(p<=mid) insert(lc,l,mid,p,v);
56     else insert(rc,mid+1,r,p,v);
57 }
58 void dl(int &x,int v){
59     if(val[x]==v) cnt[x]--;
60     else  if(v<val[x])  dl(ls[x],v);
61     else dl(rs[x],v);
62     update(x);
63 }
64 void del(int x,int l,int r,int p,int v){
65     dl(rt[x],v);
66     if(l==r) return;
67     if(p<=mid) del(lc,l,mid,p,v);
68     else del(rc,mid+1,r,p,v);
69 }
70 int count1(int x,int v){
71     if(!x) return 0;
72     int ret;
73     if(val[x]>=v) ret=count1(ls[x],v)+tot[rs[x]]+cnt[x];
74     else  ret=count1(rs[x],v);
75     return ret;
76 }
77 int count2(int x,int v){
78     if(!x) return 0;
79     int ret;
80     if(val[x]<=v) ret=count2(rs[x],v)+tot[ls[x]]+cnt[x];
81     else ret=count2(ls[x],v);
82     return ret;
83 }
84 int query(int x,int l,int r,int ll,int rr,int z){
85     if(l>r) return 0;
86     if(l==r) return b[r];
87     int t1=count1(rt[lc],ll);
88     int t2=count2(rt[lc],rr);
89     int s=tot[rt[lc]];
90     int t=t2-(s-t1);
91     if(t>=z) return  query(lc,l,mid,ll,rr,z);
92     else return query(rc,mid+1,r,ll,rr,z-t);
93 }
94 int main(){
95     int cas=1;
96    // scanf("%d",&cas);
97     while (cas--){
98         scanf("%d%d",&n,&m);
99         int t=n;
100         for(int i=1;i<=n;i++)
101             scanf("%d",&a[i]),b[i]=a[i];
102         for(int i=1;i<=m;i++){
103             char s[2];
104             scanf("%s",s);
105             if(s[0]=='C') {
106                 q[i].k=0;
107                 scanf("%d%d",&q[i].x,&q[i].y);
108                 b[++t]=q[i].y;
109             }else {
110                 q[i].k=1;
111                 scanf("%d%d%d",&q[i].x,&q[i].y,&q[i].z);
112             }
113         }
114         sort(b+1,b+t+1);
115         t=unique(b+1,b+t+1)-b-1;
116         for(int i=1;i<=n;i++){
117             int k=lower_bound(b+1,b+t+1,a[i])-b;
118             insert(1,1,t,k,i);
119         }
120         for(int i=1;i<=m;i++){
121             if(q[i].k==0) {
122                 int p=lower_bound(b+1,b+t+1,a[q[i].x])-b;
123                 del(1,1,t,p,q[i].x);
124                 a[q[i].x]=q[i].y;
125                 p=lower_bound(b+1,b+t+1,a[q[i].x])-b;
126                 insert(1,1,t,p,q[i].x);
127             }else {
128                 printf("%d\n",query(1,1,t,q[i].x,q[i].y,q[i].z));
129             }
130         }
131
132     }
133     return 0;
134
135 }
View Code

posted @ 2019-07-06 21:20  zjxxcn  阅读(150)  评论(0编辑  收藏