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大基本可以手写,,但是感觉理解还不是很深。另外定义两个数组,一个用来新建一颗主席树,所有修改的结果都在这个上面进行,而另一个是记录中间值,相当于temp的效果,不改变原始数组。。(挖个坑)
附主席树专题链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=63941#overview
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <algorithm> 5 #include <iostream> 6 using namespace std; 7 typedef long long ll; 8 const int maxn = 5e4+10; 9 int n,m,tot,idx; 10 ll a[maxn],vec[maxn*2]; 11 struct 12 { 13 int x,y,k,flag,idx; 14 } Q[maxn]; 15 16 // 主席树 17 int lson[maxn*50],rson[maxn*50],c[maxn*50],root[maxn]; //依次为左儿子 右儿子 线段树 根节点 18 int build (int l,int r) 19 { 20 int root = tot++; 21 c[root] = 0; 22 if (l != r) 23 { 24 int mid = (l + r) >> 1; 25 lson[root] = build(l,mid); 26 rson[root] = build(mid+1,r); 27 } 28 return root; 29 } 30 int update(int root,int pos,int val) 31 { 32 int new_root = tot++; 33 int tmp = new_root; 34 int l = 1,r = idx; 35 c[new_root] = c[root] + val; 36 while (l < r) 37 { 38 int mid = (l + r) >> 1; 39 if (pos <= mid) 40 { 41 rson[new_root] = rson[root]; 42 root = lson[root]; 43 lson[new_root] = tot++; 44 new_root = lson[new_root]; 45 r = mid; 46 } 47 else 48 { 49 lson[new_root] = lson[root]; 50 root = rson[root]; 51 rson[new_root] = tot++; 52 new_root = rson[new_root]; 53 l = mid + 1; 54 } 55 c[new_root] = c[root] + val; 56 } 57 return tmp; 58 } 59 // 树状数组维护 60 int s[maxn],use[maxn]; 61 inline int lowbit (int x) 62 { 63 return x & -x; 64 } 65 void add(int k,int pos,int d) 66 { 67 while (k <= n) 68 { 69 s[k] = update(s[k],pos,d); 70 k += lowbit(k); 71 } 72 } 73 int sum(int pos) 74 { 75 int res = 0; 76 while (pos) 77 { 78 res += c[lson[use[pos]]]; 79 pos -= lowbit(pos); 80 } 81 return res; 82 } 83 int query(int left,int right,int k) 84 { 85 int l_root = root[left-1]; 86 int r_root = root[right]; 87 for (int i = left-1; i > 0; i -= lowbit(i)) 88 use[i] = s[i]; 89 for (int i = right; i > 0; i -= lowbit(i)) 90 use[i] =s[i]; 91 int l = 1,r = idx; 92 while (l < r) 93 { 94 int t = sum(right) - sum(left-1) + c[lson[r_root]] - c[lson[l_root]]; 95 int mid = (l + r) >> 1; 96 if (t >= k) 97 { 98 for (int i = left-1; i > 0; i -= lowbit(i)) 99 use[i] = lson[use[i]]; 100 for (int i = right; i > 0; i -= lowbit(i)) 101 use[i] = lson[use[i]]; 102 l_root = lson[l_root]; 103 r_root = lson[r_root]; 104 r = mid; 105 } 106 else 107 { 108 for (int i = left-1; i > 0; i -= lowbit(i)) 109 use[i] = rson[use[i]]; 110 for (int i = right; i > 0; i -= lowbit(i)) 111 use[i] = rson[use[i]]; 112 l_root = rson[l_root]; 113 r_root = rson[r_root]; 114 k -= t; 115 l = mid + 1; 116 } 117 } 118 return l; 119 } 120 121 void read() 122 { 123 scanf ("%d%d",&n,&m); 124 for (int i = 1; i <= n; i++) 125 { 126 scanf ("%lld",a+i); 127 vec[idx++] = a[i]; 128 } 129 for (int i = 0; i < m; i++) 130 { 131 char op[3]; 132 scanf ("%s",op); 133 if (op[0] == 'C') 134 { 135 scanf ("%d%d",&Q[i].x,&Q[i].y); 136 Q[i].flag = 0; 137 vec[idx++] = Q[i].y; 138 } 139 if (op[0] == 'Q') 140 { 141 scanf ("%d%d%d",&Q[i].x,&Q[i].y,&Q[i].k); 142 Q[i].flag = 1; 143 } 144 } 145 } 146 int main(void) 147 { 148 #ifndef ONLINE_JUDGE 149 freopen("in.txt","r",stdin); 150 #endif 151 int T; 152 scanf ("%d",&T); 153 while (T--) 154 { 155 idx = tot = 0; 156 read(); 157 sort(vec,vec+idx); //离散化 158 idx = unique(vec,vec+idx) - vec; 159 root[0] = build(1,idx); 160 for (int i = 1; i <= n; i++) 161 { 162 int tmp = lower_bound(vec,vec+idx,a[i]) - vec ; 163 root[i] = update(root[i-1],tmp,1); 164 } 165 for (int i = 0; i <= n; i++) 166 s[i] = root[0]; 167 for (int i = 0; i < m; i++) 168 { 169 if (Q[i].flag == 0) 170 { 171 int tmp1 = lower_bound(vec,vec+idx,a[Q[i].x]) - vec ; 172 int tmp2 = lower_bound(vec,vec+idx,Q[i].y) - vec ; 173 add(Q[i].x,tmp1,-1); 174 add(Q[i].x,tmp2,1); 175 a[Q[i].x] = Q[i].y; 176 } 177 if (Q[i].flag == 1) 178 { 179 printf("%lld ",vec[query(Q[i].x,Q[i].y,Q[i].k)]); 180 } 181 } 182 } 183 return 0; 184 }