题意:n个数,q个询问 (n<=50000, q<=10000)
Q x y z 代表询问[x, y]区间里的第z小的数
C x y 代表将(从左往右数)第x个数变成y
上篇介绍了在[x, y]区间内查询第z小的数的方法(静态主席树)
本题有更新操作
若仍用上篇的做法,
每次更新一个数,需要更新的是T[i], T[i+1]... ...T[n](该数所在的树以及它后面的所有树)
因为每棵树T[i]所记录的都是前缀(1到i的数出现的次数) 因此,改变i,会影响i到n的所有树
这样,每次更新的复杂度最坏为O($n$),最坏更新q次即为O($n\times m$) 复杂度相当庞大,很明显这样做是不行的
那怎么办呢?
我们可以发现,对于改变i处的数这个操作,对于T[i], T[i+1]... ...T[n]这些树的影响是相同的
都只改变了 “原来i处的数 的数量” 和 “现在i处的数 的数量” 这两个值而已
因此,我们要用主席树来维护每个位置,对于每个位置建立线段树,(而非每个位置及其前缀)
再用树状数组来记录更新,维护前缀和,每次更新$logn$棵树
将每个位置建一棵线段树的好处是 使得每个位置可以相加减,那么就相当于用树状数组来询问区间和了
模板是kuangbin的
query用非递归的形式节约时间orz...
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], wz[N]; 8 int T[N], L[N<<5], R[N<<5], c[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[10010]; 16 17 int build(int l, int r) 18 { 19 int rt=tot++; 20 c[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 Insert(int rt, int pos, int val) 31 { 32 int newrt=tot, tmp=tot++; 33 int l=0, r=m-1; 34 c[newrt]=c[rt]+val; 35 while(l<r) 36 { 37 int m=(l+r)>>1; 38 if(pos<=m) 39 { 40 L[newrt]=tot++; 41 R[newrt]=R[rt]; 42 newrt=L[newrt]; 43 rt=L[rt]; 44 r=m; 45 } 46 else 47 { 48 R[newrt]=tot++; 49 L[newrt]=L[rt]; 50 newrt=R[newrt]; 51 rt=R[rt]; 52 l=m+1; 53 } 54 c[newrt]=c[rt]+val; 55 } 56 return tmp; 57 } 58 59 int lowbit(int x) 60 { 61 return x&(-x); 62 } 63 64 int use[N]; 65 void add(int x, int pos, int val) 66 { 67 while(x<=n) 68 { 69 S[x]=Insert(S[x], pos, val); 70 x+=lowbit(x); 71 } 72 } 73 74 int sum(int x) 75 { 76 int ret=0; 77 while(x>0) 78 { 79 ret+=c[L[use[x]]]; 80 x-=lowbit(x); 81 } 82 return ret; 83 } 84 85 int query(int left, int right, int k) 86 { 87 int lrt=T[left-1]; 88 int rrt=T[right]; 89 int l=0, r=m-1; 90 for(int i=left-1;i;i-=lowbit(i)) 91 use[i]=S[i]; 92 for(int i=right;i;i-=lowbit(i)) 93 use[i]=S[i]; 94 while(l<r) 95 { 96 int m=(l+r)>>1; 97 int tmp=sum(right)-sum(left-1)+c[L[rrt]]-c[L[lrt]]; 98 if(tmp>=k) 99 { 100 r=m; 101 for(int i=left-1;i;i-=lowbit(i)) 102 use[i]=L[use[i]]; 103 for(int i=right;i;i-=lowbit(i)) 104 use[i]=L[use[i]]; 105 lrt=L[lrt]; 106 rrt=L[rrt]; 107 } 108 else 109 { 110 l=m+1; 111 k-=tmp; 112 for(int i=left-1;i;i-=lowbit(i)) 113 use[i]=R[use[i]]; 114 for(int i=right;i;i-=lowbit(i)) 115 use[i]=R[use[i]]; 116 lrt=R[lrt]; 117 rrt=R[rrt]; 118 } 119 } 120 return l; 121 } 122 123 void Modify(int x, int p, int d) 124 { 125 while(x<=n) 126 { 127 S[x]=Insert(S[x], p, d); 128 x+=lowbit(x); 129 } 130 } 131 132 int main() 133 { 134 int t; 135 scanf("%d", &t); 136 while(t--) 137 { 138 int q; 139 scanf("%d%d", &n, &q); 140 tot=0; 141 m=0; 142 for(int i=1;i<=n;i++) 143 { 144 scanf("%d", &a[i]); 145 wz[m++]=a[i]; 146 } 147 for(int i=0;i<q;i++) 148 { 149 char s[10]; 150 scanf("%s", s); 151 if(s[0]=='Q') 152 { 153 scanf("%d%d%d", &op[i].l, &op[i].r, &op[i].k); 154 op[i].Q=1; 155 } 156 else 157 { 158 scanf("%d%d", &op[i].l, &op[i].r); 159 op[i].Q=0; 160 wz[m++]=op[i].r; 161 } 162 } 163 sort(wz, wz+m); 164 int mm=unique(wz, wz+m)-wz; 165 m=mm; 166 T[0]=build(0, m-1); 167 for(int i=1;i<=n;i++) 168 T[i]=Insert(T[i-1], lower_bound(wz, wz+m, a[i])-wz, 1); 169 for(int i=1;i<=n;i++) 170 S[i]=T[0]; 171 for(int i=0;i<q;i++) 172 { 173 if(op[i].Q) 174 printf("%d\n", wz[query(op[i].l, op[i].r, op[i].k)]); 175 else 176 { 177 Modify(op[i].l, lower_bound(wz, wz+m, a[op[i].l])-wz, -1); 178 Modify(op[i].l, lower_bound(wz, wz+m, op[i].r)-wz, 1); 179 a[op[i].l]=op[i].r; 180 } 181 } 182 } 183 return 0; 184 }