替罪羊树呢就是不用旋转的平衡树,那不旋转如何维持平衡呢?我们设定一个 α 值,每当一个点不满足大小平衡时我们就暴力重构那一部分。用平衡树维护区间位置,每个节点一棵权值线段树。查询的时候我们就把x~y区间搞出来(用一堆权值线段树和单点表示),然后类似主席树求第k小的去树上二分找一下即可。此题还要回收垃圾。。。因为内存不够!删除还有回收的时候记得传引用,因为你还要断掉他父亲和他的边。重构的时候只重构深度最小的那个结点的子树即可。复杂度 O(nlog3n)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 70010
#define alpha 0.75
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}char op[5];
inline void read_S(){
int l=0;char ch=gc();
while(ch<'A'||ch>'Z') ch=gc();
while(ch>='A'&&ch<='Z') op[++l]=ch,ch=gc();
}
int n,v[N],dfn[N],rt[N],lc[N],rc[N],root=0,ans=0,owo=0,tmp,dfnum=0;
struct node{int lc,rc,sum;}tr[10000010];
queue<int>rec;
inline int newnode(){
if(rec.empty()) return ++owo;
int x=rec.front();rec.pop();return x;
}
inline void dorec(int &p){
if(!p) return;rec.push(p);
dorec(tr[p].lc);dorec(tr[p].rc);tr[p].sum=0;p=0;
}
inline void add(int &p,int l,int r,int x,int val){
if(!p) p=newnode();tr[p].sum+=val;
if(l==r) return;int mid=l+r>>1;
if(x<=mid) add(tr[p].lc,l,mid,x,val);
else add(tr[p].rc,mid+1,r,x,val);
if(!tr[p].sum) dorec(p);
}
inline void build(int &p,int l,int r){
int mid=l+r>>1;p=dfn[mid];
for(int i=l;i<=r;++i) add(rt[p],0,70000,v[dfn[i]],1);
if(l<mid) build(lc[p],l,mid-1);
if(r>mid) build(rc[p],mid+1,r);
}
vector<int>a,a1;
inline void gao(int p,int x,int y){
int szl=tr[rt[lc[p]]].sum,sz=tr[rt[p]].sum;
if(x==1&&y==sz){a.push_back(rt[p]);return;}
if(y<=szl){gao(lc[p],x,y);return;}
if(x>szl+1){gao(rc[p],x-szl-1,y-szl-1);return;}
a1.push_back(v[p]);
if(x<=szl) gao(lc[p],x,szl);
if(y>szl+1) gao(rc[p],1,y-szl-1);
}
inline void query(int x,int y,int k){
a.clear();a1.clear();
gao(root,x,y);int l=0,r=70000;
while(l<=r){
if(l==r) break;int sum=0,mid=l+r>>1;
for(int i=0;i<a.size();++i){
int p=a[i];
sum+=tr[tr[a[i]].lc].sum;
}
for(int i=0;i<a1.size();++i) sum+=(l<=a1[i]&&a1[i]<=mid);
if(k<=sum){
for(int i=0;i<a.size();++i) a[i]=tr[a[i]].lc;r=mid;
}else{
for(int i=0;i<a.size();++i) a[i]=tr[a[i]].rc;l=mid+1,k-=sum;
}
}printf("%d\n",ans=l);
}
inline int modify(int p,int x,int val){
add(rt[p],0,70000,val,1);int szl=tr[rt[lc[p]]].sum,t;
if(szl+1==x) t=v[p],v[p]=val;
else if(x<=szl) t=modify(lc[p],x,val);
else t=modify(rc[p],x-szl-1,val);
add(rt[p],0,70000,t,-1);return t;
}
int *stack[N],top;
inline void ins(int &p,int x,int val){
if(!p){
p=++n;v[p]=val;add(rt[p],0,70000,val,1);return;
}int szl=tr[rt[lc[p]]].sum;add(rt[p],0,70000,val,1);
if(x<=szl+1){
ins(lc[p],x,val);
if(tr[rt[p]].sum*alpha<tr[rt[lc[p]]].sum) stack[++top]=&p;
}else{
ins(rc[p],x-szl-1,val);
if(tr[rt[p]].sum*alpha<tr[rt[rc[p]]].sum) stack[++top]=&p;
}
}
inline void del(int &p){
if(!p) return;dorec(rt[p]);
del(lc[p]);dfn[++dfnum]=p;del(rc[p]);p=0;
}
inline void rebuild(int &p){
dfnum=0;del(p);build(p,1,dfnum);
}
inline void insert(int x,int val){//在x前面插入val
top=0;ins(root,x,val);
if(top) rebuild(*stack[top]);
}
int main(){
// freopen("a.in","r",stdin);
n=read();
for(int i=1;i<=n;++i) v[i]=read(),dfn[i]=i;
build(root,1,n);int m=read();
while(m--){
read_S();
int x=read()^ans,y=read()^ans;
if(op[1]=='Q') query(x,y,read()^ans);
else if(op[1]=='M') modify(root,x,y);
else insert(x,y);
}
}