BZOJ上是权限题,洛谷赞啊。
求区间 K 大数很简单。
但是如果修改某个数的话,那么就得把这个数及后面所建的主席树都更新一遍 nlogn,显然不行。
所以可以在外面套一个树状数组来优化,树状数组的每一个节点都表示某个区间的主席树。
所以可以通过树状数组来求前缀和主席树。
具体实现看代码。
——代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 5 const int MAXN = 20005; 6 int n, m, tot, cnt, size, t1, t2; 7 int a[MAXN], b[MAXN], x[MAXN], y[MAXN], z[MAXN], q1[MAXN], q2[MAXN], root[MAXN], ls[MAXN * 100], rs[MAXN * 100], sum[MAXN * 100]; 8 char s[MAXN]; 9 10 inline int read() 11 { 12 int x = 0; 13 char ch = getchar(); 14 for(; !isdigit(ch); ch = getchar()); 15 for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0'; 16 return x; 17 } 18 19 inline void insert(int &now, int l, int r, int x, int v) 20 { 21 if(!now) now = ++cnt; 22 sum[now] += v; 23 if(l == r) return; 24 int mid = (l + r) >> 1; 25 if(x <= mid) insert(ls[now], l, mid, x, v); 26 else insert(rs[now], mid + 1, r, x, v); 27 } 28 29 inline int query(int l, int r, int x) 30 { 31 if(l == r) return l; 32 int i, mid = (l + r) >> 1, ans = 0; 33 for(i = 1; i <= t1; i++) ans -= sum[ls[q1[i]]]; 34 for(i = 1; i <= t2; i++) ans += sum[ls[q2[i]]]; 35 if(x <= ans) 36 { 37 for(i = 1; i <= t1; i++) q1[i] = ls[q1[i]]; 38 for(i = 1; i <= t2; i++) q2[i] = ls[q2[i]]; 39 return query(l, mid, x); 40 } 41 else 42 { 43 for(i = 1; i <= t1; i++) q1[i] = rs[q1[i]]; 44 for(i = 1; i <= t2; i++) q2[i] = rs[q2[i]]; 45 return query(mid + 1, r, x - ans); 46 } 47 } 48 49 int main() 50 { 51 int i, j, l, r; 52 n = read(); 53 m = read(); 54 for(i = 1; i <= n; i++) a[i] = read(), b[++tot] = a[i]; 55 for(i = 1; i <= m; i++) 56 { 57 for(s[i] = getchar(); s[i] != 'Q' && s[i] != 'C'; s[i] = getchar()); 58 if(s[i] == 'C') x[i] = read(), z[i] = read(), b[++tot] = z[i]; 59 else x[i] = read(), y[i] = read(), z[i] = read(); 60 } 61 62 std::sort(b + 1, b + tot + 1); 63 size = std::unique(b + 1, b + tot + 1) - (b + 1); 64 for(i = 1; i <= n; i++) a[i] = std::lower_bound(b + 1, b + size + 1, a[i]) - b; 65 for(i = 1; i <= m; i++) 66 if(s[i] == 'C') 67 z[i] = std::lower_bound(b + 1, b + size + 1, z[i]) - b; 68 69 for(i = 1; i <= n; i++) 70 for(j = i; j <= size; j += j & -j) 71 insert(root[j], 1, size, a[i], 1); 72 73 for(i = 1; i <= m; i++) 74 if(s[i] == 'Q') 75 { 76 t1 = t2 = 0; 77 for(j = x[i] - 1; j; j -= j & -j) q1[++t1] = root[j]; 78 for(j = y[i]; j; j -= j & -j) q2[++t2] = root[j]; 79 printf("%d ", b[query(1, size, z[i])]); 80 } 81 else 82 { 83 for(j = x[i]; j <= size; j += j & -j) insert(root[j], 1, size, a[x[i]], -1); 84 a[x[i]] = z[i]; 85 for(j = x[i]; j <= size; j += j & -j) insert(root[j], 1, size, z[i], 1); 86 } 87 return 0; 88 }