动态主席树,相当于树套树,,注意到我们修改的时候影响的是后面,,相当于前缀和的形式,,外层树状数组,,内部要用主席树,,自己打的,,但看的别人模板,,这样不好,,但人家的代码却是比较巧妙,,避免了很多问题,,学习吧,,注意这里修改都要动态开节点并且共用,,,这样树状数组修改才不会修改到同一个节点是不是啊,,,被这个想法卡了好久,,终于还是小恐龙喷了一下火我才明白的,,,
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<algorithm>
#define N 10000
#define M 5000000
using namespace std;
struct data{ char ch; int x,y,z;};
struct node{ int id,val;};
struct tree{ int son[2],sum;};
data que[N+5];
node s[(N<<1)+5];
tree A[M+5];
int n,m,posi,a[N+5],pos[(N<<1)+5],cnt,root[(N<<1)+5],p,q,P[(N<<1)+5],Q[(N<<1)+5],num[(N<<1)+5];
inline bool cmp(node a,node b){ return a.val<b.val;}
inline int lowbit(int x){ return (x&(-x));}
inline int getnum(){
char c; int num;
while (!isdigit(c = getchar()));
num = c -'0';
while (isdigit(c = getchar())) num = 10 * num + c - '0';
return num;
}
void init(){
n = getnum(); m = getnum(); posi = 0; cnt = n;
for (int i = 1;i <= n; ++i) a[i] = getnum(),s[i].val = a[i],s[i].id = i;
for (int i = 1;i <= m; ++i){
cin>>que[i].ch;
que[i].x = getnum();
que[i].y = getnum();
if (que[i].ch == 'Q') que[i].z = getnum();
else s[++cnt].val = que[i].y,s[cnt].id = i + n;
}
sort(s + 1,s + cnt + 1,cmp);
s[0].val = -1;
for (int i = 1;i <= cnt; ++i){
if (s[i].val != s[i-1].val) posi++;
pos[s[i].id] = posi;
num[posi] = s[i].val;
}
}
inline void build(int l,int r,int &rt){
int mid = (l + r)>>1;
rt = ++cnt; A[rt].sum = 0;
if (l == r) return;
build(l,mid,A[rt].son[0]);
build(mid+1,r,A[rt].son[1]);
}
inline void update(int rt){ A[rt].sum = A[A[rt].son[0]].sum + A[A[rt].son[1]].sum;}
inline void change(int last,int l,int r,int &rt,int x,int c){
int mid = (l + r)>>1;
rt = ++cnt;
A[rt].son[0] = A[last].son[0]; A[rt].son[1] = A[last].son[1]; A[rt].sum = A[last].sum + c;
if (l == r) return;
if (x <= mid) change(A[last].son[0],l,mid,A[rt].son[0],x,c);
if (x > mid ) change(A[last].son[1],mid + 1,r,A[rt].son[1],x,c);
update(rt);
}
inline void add(int s,int x,int c){
for (int i = s; i <= posi; i += lowbit(i)) change(root[i],1,posi,root[i],x,c);}
inline int query(int l,int r,int k){
int mid = (l + r)>>1;
if (l == r) return l;
int suma = 0,sumb = 0;
for (int i = 1;i <= p; ++i) suma += A[A[P[i]].son[0]].sum;
for (int i = 1;i <= q; ++i) sumb += A[A[Q[i]].son[0]].sum;
int del = sumb - suma;
bool t;
if (k <= del) t = 0; else t = 1;
for (int i = 1;i <= p; ++i) P[i] = A[P[i]].son[t];
for (int i = 1;i <= q; ++i) Q[i] = A[Q[i]].son[t];
if (!t) return query(l,mid,k);
else return query(mid+1,r,k - del);
}
inline int ask(int a,int b,int c){
p = 0,q = 0;
for (;a;a -= lowbit(a)) P[++p] = root[a];
for (;b;b -= lowbit(b)) Q[++q] = root[b];
return query(1,posi,c);
}
void DO_IT(){
cnt = 0;
build(1,posi,root[0]);
for (int i = 1;i <= n; ++i) add(i,pos[i],1);
for (int i = 1;i <= m; ++i)
{
if (que[i].ch == 'Q') printf("%d\n",num[ask(que[i].x-1,que[i].y,que[i].z)]);
else {
add(que[i].x,pos[que[i].x],-1);
pos[que[i].x] = pos[i+n];
add(que[i].x,pos[que[i].x],1);
}
}
}
int main(){
init();
DO_IT();
return 0;
}