題意:n個數,q個詢問 (n<=50000, q<=10000)html
Q x y z 表明詢問[x, y]區間裏的第z小的數node
C x y 表明將(從左往右數)第x個數變成yc++
上篇介紹了在[x, y]區間內查詢第z小的數的方法(靜態主席樹)數組
本題有更新操做ide
若仍用上篇的作法,ui
每次更新一個數,須要更新的是T[i], T[i+1]... ...T[n](該數所在的樹以及它後面的全部樹)spa
由於每棵樹T[i]所記錄的都是前綴(1到i的數出現的次數) 所以,改變i,會影響i到n的全部樹3d
這樣,每次更新的複雜度最壞爲O($n$),最壞更新q次即爲O($n\times m$) 複雜度至關龐大,很明顯這樣作是不行的code
那怎麼辦呢?htm
咱們能夠發現,對於改變i處的數這個操做,對於T[i], T[i+1]... ...T[n]這些樹的影響是相同的
都只改變了 「原來i處的數 的數量」 和 「如今i處的數 的數量」 這兩個值而已
咱們只要在原來的基礎上增長一類樹, 用它們來維護更新掉的數
即用樹狀數組來記錄更新,每次更新$logn$棵樹
下面來演示一下建樹到查詢的過程:
好比此題的第一個案例
5 3 3 2 1 4 7 Q 1 4 3 C 2 6 Q 2 5 3
先將序列以及要更新的數(C操做)離散化
即3 2 1 4 7 、 6 ---->(排序) ----> 1 2 3 4 6 7
那麼咱們就須要建一棵這樣的樹:
(圈裏的都是結點的編號, 四、五、六、九、十、11號結點表明的分別是一、二、三、四、六、7)
(四、五、九、10你也能夠任意做爲6或11的兒子, 遞歸生成的是相似這樣的, 這並不重要)
對於3 2 1 4 7(先無論須要更新的6)建完樹見下圖(建樹過程同靜態的,不明白的戳這裏,上篇博客有講)
(紅色的是個數, 相同結點的個數省略了,同前一棵樹)
對於C操做以前的Q,就跟靜態的相似,減一減 找就行了
而後下面要更新了
對於更新, 咱們不改變這些已經建好的樹, 而是另建一批樹S,用來記錄更新,而這批線段樹,咱們用樹狀數組來維護
也就是樹狀數組的每一個節點都是一顆線段樹
一開始,S[0]、S[1]、S[2]、S[3]、S[4]、S[5](樹狀數組的每一個節點)這些都與T[0]相同(也就是每一個節點建了一棵空樹)
對於C 2 6 這個操做, 咱們只須要減去一個2,加上一個6便可
對於減去2
(樹狀數組i+lowbit(i)爲i的父親節點, 修改i,就要把i的全部父親節點都修改了)
2在樹狀數組中出現的位置是 二、2+lowbit(2)=4 這兩個位置,
所以要更新的是S[2]和S[4]這兩個節點中的樹
刪去2後是這樣
加上一個6 (一樣是對於2號位置, 所以須要更新的還是S[2]和S[4])
加上以後是這樣
當查詢的時候, 對樹T的操做與靜態的一致,另外再加上S樹的值就行了
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 #define lson l, m 5 #define rson m+1, r 6 const int N=60005; 7 int a[N], Hash[N]; 8 int T[N], L[N<<5], R[N<<5], sum[N<<5]; 9 int S[N]; 10 int n, m, tot; 11 struct node 12 { 13 int l, r, k; 14 bool Q; 15 }op[10005]; 16 17 int build(int l, int r) 18 { 19 int rt=(++tot); 20 sum[rt]=0; 21 if(l!=r) 22 { 23 int m=(l+r)>>1; 24 L[rt]=build(lson); 25 R[rt]=build(rson); 26 } 27 return rt; 28 } 29 30 int update(int pre, int l, int r, int x, int val) 31 { 32 int rt=(++tot); 33 L[rt]=L[pre], R[rt]=R[pre], sum[rt]=sum[pre]+val; 34 if(l<r) 35 { 36 int m=(l+r)>>1; 37 if(x<=m) 38 L[rt]=update(L[pre], lson, x, val); 39 else 40 R[rt]=update(R[pre], rson, x, val); 41 } 42 return rt; 43 } 44 45 int lowbit(int x) 46 { 47 return x&(-x); 48 } 49 50 int use[N]; 51 void add(int x, int pos, int val) 52 { 53 while(x<=n) 54 { 55 S[x]=update(S[x], 1, m, pos, val); 56 x+=lowbit(x); 57 } 58 } 59 60 int Sum(int x) 61 { 62 int ret=0; 63 while(x>0) 64 { 65 ret+=sum[L[use[x]]]; 66 x-=lowbit(x); 67 } 68 return ret; 69 } 70 71 int query(int u, int v, int lr, int rr, int l, int r, int k) 72 { 73 if(l>=r) 74 return l; 75 int m=(l+r)>>1; 76 int tmp=Sum(v)-Sum(u)+sum[L[rr]]-sum[L[lr]]; 77 if(tmp>=k) 78 { 79 for(int i=u;i;i-=lowbit(i)) 80 use[i]=L[use[i]]; 81 for(int i=v;i;i-=lowbit(i)) 82 use[i]=L[use[i]]; 83 return query(u, v, L[lr], L[rr], lson, k); 84 } 85 else 86 { 87 for(int i=u;i;i-=lowbit(i)) 88 use[i]=R[use[i]]; 89 for(int i=v;i;i-=lowbit(i)) 90 use[i]=R[use[i]]; 91 return query(u, v, R[lr], R[rr], rson, k-tmp); 92 } 93 } 94 95 void modify(int x, int p, int d) 96 { 97 while(x<=n) 98 { 99 S[x]=update(S[x], 1, m, p, d); 100 x+=lowbit(x); 101 } 102 } 103 104 int main() 105 { 106 int t; 107 scanf("%d", &t); 108 while(t--) 109 { 110 int q; 111 scanf("%d%d", &n, &q); 112 tot=0; 113 m=0; 114 for(int i=1;i<=n;i++) 115 { 116 scanf("%d", &a[i]); 117 Hash[++m]=a[i]; 118 } 119 for(int i=0;i<q;i++) 120 { 121 char s[10]; 122 scanf("%s", s); 123 if(s[0]=='Q') 124 { 125 scanf("%d%d%d", &op[i].l, &op[i].r, &op[i].k); 126 op[i].Q=1; 127 } 128 else 129 { 130 scanf("%d%d", &op[i].l, &op[i].r); 131 op[i].Q=0; 132 Hash[++m]=op[i].r; 133 } 134 } 135 sort(Hash+1, Hash+1+m); 136 int mm=unique(Hash+1, Hash+1+m)-Hash-1; 137 m=mm; 138 T[0]=build(1, m); 139 for(int i=1;i<=n;i++) 140 T[i]=update(T[i-1], 1, m, lower_bound(Hash+1, Hash+1+m, a[i])-Hash, 1); 141 for(int i=1;i<=n;i++) 142 S[i]=T[0]; 143 for(int i=0;i<q;i++) 144 { 145 if(op[i].Q) 146 { 147 for(int j=op[i].l-1;j;j-=lowbit(j)) 148 use[j]=S[j]; 149 for(int j=op[i].r;j;j-=lowbit(j)) 150 use[j]=S[j]; 151 printf("%d\n", Hash[query(op[i].l-1, op[i].r, T[op[i].l-1], T[op[i].r], 1, m, op[i].k)]); 152 } 153 else 154 { 155 modify(op[i].l, lower_bound(Hash+1, Hash+1+m, a[op[i].l])-Hash, -1); 156 modify(op[i].l, lower_bound(Hash+1, Hash+1+m, op[i].r)-Hash, 1); 157 a[op[i].l]=op[i].r; 158 } 159 } 160 } 161 return 0; 162 }