ZOJ 2112 Dynamic Rankings (动态第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.
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
主席树太神了。
这题是动态第k大。
如果是不修改,直接主席树就可以了。
要修改要套如树状数组求和。
参考链接:
http://blog.csdn.net/acm_cxlove/article/details/8565309
http://www.cnblogs.com/Rlemon/archive/2013/05/24/3096264.html
http://seter.is-programmer.com/posts/31907.html
http://blog.csdn.net/metalseed/article/details/8045038
1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013-9-8 8:53:54 4 File Name :F:\2013ACM练习\专题学习\主席树\ZOJ2112.cpp 5 ************************************************ */ 6 7 #include <stdio.h> 8 #include <string.h> 9 #include <iostream> 10 #include <algorithm> 11 #include <vector> 12 #include <queue> 13 #include <set> 14 #include <map> 15 #include <string> 16 #include <math.h> 17 #include <stdlib.h> 18 #include <time.h> 19 using namespace std; 20 21 const int MAXN = 60010; 22 const int M = 2500010; 23 int n,q,m,tot; 24 int a[MAXN], t[MAXN]; 25 int T[MAXN], lson[M], rson[M],c[M]; 26 int S[MAXN]; 27 28 struct Query 29 { 30 int kind; 31 int l,r,k; 32 }query[10010]; 33 34 void Init_hash(int k) 35 { 36 sort(t,t+k); 37 m = unique(t,t+k) - t; 38 } 39 int hash(int x) 40 { 41 return lower_bound(t,t+m,x)-t; 42 } 43 int build(int l,int r) 44 { 45 int root = tot++; 46 c[root] = 0; 47 if(l != r) 48 { 49 int mid = (l+r)/2; 50 lson[root] = build(l,mid); 51 rson[root] = build(mid+1,r); 52 } 53 return root; 54 } 55 56 int Insert(int root,int pos,int val) 57 { 58 int newroot = tot++, tmp = newroot; 59 int l = 0, r = m-1; 60 c[newroot] = c[root] + val; 61 while(l < r) 62 { 63 int mid = (l+r)>>1; 64 if(pos <= mid) 65 { 66 lson[newroot] = tot++; rson[newroot] = rson[root]; 67 newroot = lson[newroot]; root = lson[root]; 68 r = mid; 69 } 70 else 71 { 72 rson[newroot] = tot++; lson[newroot] = lson[root]; 73 newroot = rson[newroot]; root = rson[root]; 74 l = mid+1; 75 } 76 c[newroot] = c[root] + val; 77 } 78 return tmp; 79 } 80 81 int lowbit(int x) 82 { 83 return x&(-x); 84 } 85 int use[MAXN]; 86 void add(int x,int pos,int val) 87 { 88 while(x <= n) 89 { 90 S[x] = Insert(S[x],pos,val); 91 x += lowbit(x); 92 } 93 } 94 int sum(int x) 95 { 96 int ret = 0; 97 while(x > 0) 98 { 99 ret += c[lson[use[x]]]; 100 x -= lowbit(x); 101 } 102 return ret; 103 } 104 int Query(int left,int right,int k) 105 { 106 int left_root = T[left-1]; 107 int right_root = T[right]; 108 int l = 0, r = m-1; 109 for(int i = left-1;i;i -= lowbit(i)) use[i] = S[i]; 110 for(int i = right;i ;i -= lowbit(i)) use[i] = S[i]; 111 while(l < r) 112 { 113 int mid = (l+r)/2; 114 int tmp = sum(right) - sum(left-1) + c[lson[right_root]] - c[lson[left_root]]; 115 if(tmp >= k) 116 { 117 r = mid; 118 for(int i = left-1; i ;i -= lowbit(i)) 119 use[i] = lson[use[i]]; 120 for(int i = right; i; i -= lowbit(i)) 121 use[i] = lson[use[i]]; 122 left_root = lson[left_root]; 123 right_root = lson[right_root]; 124 } 125 else 126 { 127 l = mid+1; 128 k -= tmp; 129 for(int i = left-1; i;i -= lowbit(i)) 130 use[i] = rson[use[i]]; 131 for(int i = right;i ;i -= lowbit(i)) 132 use[i] = rson[use[i]]; 133 left_root = rson[left_root]; 134 right_root = rson[right_root]; 135 } 136 } 137 return l; 138 } 139 void Modify(int x,int p,int d) 140 { 141 while(x <= n) 142 { 143 S[x] = Insert(S[x],p,d); 144 x += lowbit(x); 145 } 146 } 147 148 int main() 149 { 150 //freopen("in.txt","r",stdin); 151 //freopen("out.txt","w",stdout); 152 int Tcase; 153 scanf("%d",&Tcase); 154 while(Tcase--) 155 { 156 scanf("%d%d",&n,&q); 157 tot = 0; 158 m = 0; 159 for(int i = 1;i <= n;i++) 160 { 161 scanf("%d",&a[i]); 162 t[m++] = a[i]; 163 } 164 char op[10]; 165 for(int i = 0;i < q;i++) 166 { 167 scanf("%s",op); 168 if(op[0] == 'Q') 169 { 170 query[i].kind = 0; 171 scanf("%d%d%d",&query[i].l,&query[i].r,&query[i].k); 172 } 173 else 174 { 175 query[i].kind = 1; 176 scanf("%d%d",&query[i].l,&query[i].r); 177 t[m++] = query[i].r; 178 } 179 } 180 Init_hash(m); 181 T[0] = build(0,m-1); 182 for(int i = 1;i <= n;i++) 183 T[i] = Insert(T[i-1],hash(a[i]),1); 184 for(int i = 1;i <= n;i++) 185 S[i] = T[0]; 186 for(int i = 0;i < q;i++) 187 { 188 if(query[i].kind == 0) 189 printf("%d\n",t[Query(query[i].l,query[i].r,query[i].k)]); 190 else 191 { 192 Modify(query[i].l,hash(a[query[i].l]),-1); 193 Modify(query[i].l,hash(query[i].r),1); 194 a[query[i].l] = query[i].r; 195 } 196 } 197 } 198 return 0; 199 }