树状数组套主席树,用于解决支持修改的区间k大问题。
由于主席树是一种前缀和,可以用树状数组将修改从n^2*loginf优化到n*logn*loginf。
板子题没有太多解释,直接挂代码。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
#define ll long long
#define db double
#define ldb long double
#define pli pair<ll,int>
#define mkp make_pair
#define X first
#define Y second
const int N=50005,inf=1000000000;
struct TREE{int lc,rc,sum;}T[2000000];
int n,a[N],rt[N],numl[N],lnl,numr[N],lnr,tot;
void add(int x,int y,int l,int r,int &num){
if(!num)num=++tot;
T[num].sum+=y;
if(l==r)return;
int mid=l+r>>1;
if(x>mid)add(x,y,mid+1,r,T[num].rc);
else add(x,y,l,mid,T[num].lc);
}
int kth(int k,int l,int r){
if(l==r)return l;
int i,S=0;
rep(i,1,lnr)S+=T[T[numr[i]].lc].sum;
rep(i,1,lnl)S-=T[T[numl[i]].lc].sum;
if(k>S){
rep(i,1,lnr)numr[i]=T[numr[i]].rc;
rep(i,1,lnl)numl[i]=T[numl[i]].rc;
return kth(k-S,l+r+2>>1,r);
}
rep(i,1,lnr)numr[i]=T[numr[i]].lc;
rep(i,1,lnl)numl[i]=T[numl[i]].lc;
return kth(k,l,l+r>>1);
}
int main(){
int Q,i,z,x,y,k;char str[2];
scanf("%d%d",&n,&Q);
rep(i,1,n){
scanf("%d",&a[i]);
for(z=i;z<=n;z+=z&-z)
add(a[i],1,0,inf,rt[z]);
}
while(Q--){
scanf("%s%d%d",str,&x,&y);
if(str[0]=='C'){
for(z=x;z<=n;z+=z&-z){
add(a[x],-1,0,inf,rt[z]);
add(y,1,0,inf,rt[z]);
}
a[x]=y;
}
else{
scanf("%d",&k);
for(lnl=0,z=x-1;z;z-=z&-z)numl[++lnl]=rt[z];
for(lnr=0,z=y;z;z-=z&-z)numr[++lnr]=rt[z];
printf("%d\n",kth(k,0,inf));
}
}
return 0;
}