题目大意:带修改的区间第k大
就是树状数组套可持久线段树
#include<cstdio>
#include<iostream>
using namespace std;
const int maxt=10000011,maxn=1e9,maxm=10011,maxch=maxt;
char buf[maxch],*wbuf=buf;
inline void read(int &x){
x=0;while (*wbuf<'0'||*wbuf>'9') ++wbuf;
while ('0'<=*wbuf&&*wbuf<='9')x=x*10+*wbuf++-'0';
}
inline void getch(char &ch){
while (*wbuf!='Q'&&*wbuf!='C') ++wbuf;ch=*wbuf;
}
int size[maxt],lson[maxt],rson[maxt];
int tot;
void ins(int p,int l,int r,int m,int add){
size[p]+=add;
if (l==r) return;
int mid=(l+r)>>1;
if (m<=mid) ins(lson[p]?lson[p]:lson[p]=++tot,l,mid,m,add);
else ins(rson[p]?rson[p]:rson[p]=++tot,mid+1,r,m,add);
}
int p1[17],p2[17];
void query(int a,int b,int c){
int sum1=0,sum2=0,l=0,r=maxn;
for (int i=a-1;i;i-=i&(-i)) p1[++sum1]=i;
for (int i=b;i;i-=i&(-i)) p2[++sum2]=i;
while (l<r){
int mid=(l+r)>>1,rank=0;
for (int i=1;i<=sum1;++i) rank-=size[lson[p1[i]]];
for (int i=1;i<=sum2;++i) rank+=size[lson[p2[i]]];
if (c<=rank){
r=mid;
for (int i=1;i<=sum1;++i) p1[i]=lson[p1[i]];
for (int i=1;i<=sum2;++i) p2[i]=lson[p2[i]];
}else{
l=mid+1;c-=rank;
for (int i=1;i<=sum1;++i) p1[i]=rson[p1[i]];
for (int i=1;i<=sum2;++i) p2[i]=rson[p2[i]];
}
}
printf("%d\n",l);
}
int n,m;
int a[maxm];
void init(){
fread(buf,1,maxch,stdin);
read(n);read(m);tot=n;
for (int i=1;i<=n;++i){
read(a[i]);
for (int j=i;j<=n;j+=j&(-j))
ins(j,0,maxn,a[i],1);
}
}
void work(){
char op;int x,y,z;
while (m--){
getch(op);
if (op=='C'){
read(x);read(y);
for (int i=x;i<=n;i+=i&(-i)){
ins(i,0,maxn,y,1);ins(i,0,maxn,a[x],-1);
}
a[x]=y;
}
else{read(x);read(y);read(z);query(x,y,z);}
}
}
int main(){
init();
work();
return 0;
}