传送门
动态主席树模板题,感谢hzwer的模板,自己改动了一点小地方。
这就是传说中的树套树?
#include
#include
#include
#include
using namespace std;
const int max_n=1e4+5;
const int max_m=1e4+5;
const int max_log=30;
const int max_tree=3e6+5;
char opt[10];
int n,m,a,b,t,sz,N,cnt;
int val[max_n],A[max_m],B[max_m],K[max_m],flag[max_m];
int num[max_n*2],hash[max_n*2],root[max_n*2],L[max_log],R[max_log];
int sum[max_tree],ls[max_tree],rs[max_tree];
inline int find(int x){
int l=1,r=N,mid;
while (l<=r){
mid=(l+r)>>1;
if (hash[mid]1;
else r=mid-1;
}
return l;
}
inline void build(int last,int l,int r,int &now,int x,int v){
int mid=(l+r)>>1;
now=++sz;
sum[now]=sum[last]+v; ls[now]=ls[last]; rs[now]=rs[last];
if (l==r) return;
if (x<=mid) build(ls[last],l,mid,ls[now],x,v);
else build(rs[last],mid+1,r,rs[now],x,v);
}
inline int query(int l,int r,int k){
int mid=(l+r)>>1;
if (l==r) return l;
int suml=0,sumr=0;
for (int i=1;i<=a;++i) suml+=sum[ls[L[i]]];
for (int i=1;i<=b;++i) sumr+=sum[ls[R[i]]];
if (sumr-suml>=k){
for (int i=1;i<=a;++i) L[i]=ls[L[i]];
for (int i=1;i<=b;++i) R[i]=ls[R[i]];
return query(l,mid,k);
}
else{
for (int i=1;i<=a;++i) L[i]=rs[L[i]];
for (int i=1;i<=b;++i) R[i]=rs[R[i]];
return query(mid+1,r,k-(sumr-suml));
}
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i) scanf("%d",&val[i]),num[++cnt]=val[i];
for (int i=1;i<=m;++i){
scanf("%s",opt);
if (opt[0]=='C'){
scanf("%d%d",&A[i],&B[i]);
num[++cnt]=B[i];
}
else{
flag[i]=1;
scanf("%d%d%d",&A[i],&B[i],&K[i]);
}
}
sort(num+1,num+cnt+1);
hash[++N]=num[1];
for (int i=2;i<=cnt;++i)
if (num[i]!=num[i-1]) hash[++N]=num[i];
for (int i=1;i<=n;++i){
t=find(val[i]);
for (int j=i;j<=n;j+=j&(-j))
build(root[j],1,N,root[j],t,1);
}
for (int i=1;i<=m;++i)
if (flag[i]){
a=0,b=0,A[i]--;
for (int j=A[i];j>=1;j-=j&(-j)) L[++a]=root[j];
for (int j=B[i];j>=1;j-=j&(-j)) R[++b]=root[j];
printf("%d\n",hash[query(1,N,K[i])]);
}
else{
t=find(val[A[i]]);
for (int j=A[i];j<=n;j+=j&(-j)) build(root[j],1,N,root[j],t,-1);
val[A[i]]=B[i];
t=find(val[A[i]]);
for (int j=A[i];j<=n;j+=j&(-j)) build(root[j],1,N,root[j],t,1);
}
}