题目大意:rt,维护一个数据结构 ,支持带插入区间K小值
如果不带插入的话,就BIT+主席树,而带了插入,所以外面只能套一个平衡树,而splay和treap什么还要一直转,TLE是稳稳的,那么我们就选择了替罪羊树,因为不用转,然后重建的时候暴力重构就好了,那么对于修改来说先在内层线段树中删除再加入就好了,而k小值就是二分答案就好了,不过还是码的心累啊。
code:
#define MAXN 1401000 #define inf 70000 #include <iostream> #include <vector> #include <stdio.h> #include <algorithm> using namespace std; int n,q,len,last_ans,li[MAXN],num; int val_used[MAXN],Num; const double alpha = 0.755; template<typename _t> inline _t read(){ _t x=0; int f=1; char ch=getchar(); for(;ch>'9'||ch<'0';ch=getchar())if(ch=='-')f=-f; for(;ch<='9'&&ch>='0';ch=getchar())x=x*10+(ch^48); return (_t)x*f; } //Segment Tree struct Tree{ Tree *ls,*rs; int s,l,r,m; void *operator new (size_t); void operator delete (void *p); Tree(int x,int y); Tree(){ s=0; ls=rs=NULL; l=r=m=0; } }*S,*T,*used[MAXN],*Nil=new Tree(); Tree :: Tree(int x,int y){ l=x;r=y; m=l+r>>1; ls=rs=Nil; s=0; } vector<Tree*>bin; void* Tree :: operator new (size_t){ Tree *p; if(!bin.empty()){ p=bin.back(); bin.pop_back(); } else{ if(S==T){ S=new Tree[1<<15]; T=S+(1<<15); } p=S++; } return p; } void Tree :: operator delete (void *p){ bin.push_back((Tree*)p); } struct node{ node *ls,*rs; Tree *root; int s,v; inline void Maintain(){ s=ls->s+rs->s+1; } inline bool bad(){ return ls->s>s*alpha||rs->s>s*alpha; } void* operator new (size_t); void operator delete (void *p); node(){ s=0;v=0; root=Nil; ls=rs=NULL; } node(int x); }*null=new node(),*C,*mempool,*lst[MAXN],*root; vector<node*>Stack; node :: node(int x){ s=1;v=x; root=Nil; ls=rs=null; } void* node :: operator new (size_t){ node *p; if(!Stack.empty()){ p=Stack.back(); Stack.pop_back(); } else{ if(C==mempool){ C=new node[1<<15]; mempool=C+(1<<15); } p=C++; } return p; } void node :: operator delete (void *p){ Stack.push_back((node*)p); } inline int Rank(Tree *o,int x){ int ans = 0; while(o!=Nil){ if(o->l==o->r)return ans; if(x<=o->m)o=o->ls; else ans+=o->ls->s,o=o->rs; } return ans; } void Tree_insert(Tree *&o,int l,int r,int val){ if(o==Nil)o=new Tree(l,r); o->s++; if(l==r)return; if(val<=o->m)Tree_insert(o->ls,l,o->m,val); else Tree_insert(o->rs,o->m+1,r,val); } void dfs(Tree *&o){ if(o==Nil)return; dfs(o->ls); dfs(o->rs); delete o; } void travel(node *o){ if(o==null)return; travel(o->ls); lst[++len]=o; li[len]=o->v; dfs(o->root); o->root=Nil; travel(o->rs); } node* divide(int l,int r){ if(l>r)return null; int m=l+r>>1; for(int i=l;i<=r;i++)Tree_insert(lst[m]->root,0,inf,li[i]); lst[m]->ls=divide(l,m-1); lst[m]->rs=divide(m+1,r); lst[m]->Maintain(); return lst[m]; } void rebuild(node *&o){ len=0; travel(o); o=divide(1,len); } node ** insert(node *&o,int pos,int w){ if(o==null){ o=new node(w); Tree_insert(o->root,0,inf,w); return &null; } Tree_insert(o->root,0,inf,w); node **p; if(pos<=o->ls->s+1)p=insert(o->ls,pos,w); else p=insert(o->rs,pos-o->ls->s-1,w); if(o->bad())p=&o; o->Maintain(); return p; } void Insert(int pos,int w){ node **p=insert(root,pos,w); if(*p!=null)rebuild(*p); } void Tree_erase(Tree *&o,int w){ o->s--; if(o->l==o->r){ if(o->s==0)delete o,o=Nil; return; } if(w<=o->m)Tree_erase(o->ls,w); else Tree_erase(o->rs,w); if(!o->s)delete o,o=Nil; } void erase(node *o,int pos,int w){ Tree_erase(o->root,w); if(pos==o->ls->s+1)return; if(pos<=o->ls->s)erase(o->ls,pos,w); else erase(o->rs,pos-o->ls->s-1,w); } void get_Tree(node *o,int l,int r){ if(o==null)return; if(l<=1&&o->s<=r){ used[++num]=o->root; return; } if(l<=o->ls->s)get_Tree(o->ls,l,r); if(l<=o->ls->s+1&&r>=o->ls->s+1)val_used[++Num]=o->v; if(o->ls->s+1<r)get_Tree(o->rs,l-o->ls->s-1,r-o->ls->s-1); } int get_rank(int x){ int ans = 0; for(int i=1;i<=num;i++) ans+=Rank(used[i],x); for(int i=1;i<=Num;i++) if(val_used[i]<x)ans++; else break; return ans; } void Query(){ int l=read<int>()^last_ans,r=read<int>()^last_ans,k=read<int>()^last_ans; num=Num=0; get_Tree(root,l,r); sort(val_used+1,val_used+1+Num); int L=0,R=inf,ans; while(L<=R){ int mid = L+R>>1; if(get_rank(mid)+1<=k)ans=mid,L=mid+1; else R=mid-1; } last_ans=ans; printf("%d ",ans); } int __read_char(){ char ch=getchar(); for(;ch!='M'&&ch!='I'&&ch!='Q';ch=getchar()); if(ch=='Q')return 1; if(ch=='I')return 2; return 3; } void __insert(){ int pos=read<int>()^last_ans,val=read<int>()^last_ans; Insert(pos,val); } inline int __find_val(int pos){ node *p=root; while(p!=null){ if(p->ls->s+1==pos)return p->v; else if(p->ls->s>=pos)p=p->ls; else pos-=p->ls->s+1,p=p->rs; } } void __change(node *o,int pos,int val){ Tree_insert(o->root,0,inf,val); if(pos==o->ls->s+1){ o->v=val; return; } if(pos<=o->ls->s)__change(o->ls,pos,val); else __change(o->rs,pos-o->ls->s-1,val); } void change(){ int pos=read<int>()^last_ans,val=read<int>()^last_ans; erase(root,pos,__find_val(pos)); __change(root,pos,val); } void __dfs(node *root){ if(root==null)return; __dfs(root->ls); printf("%d ",root->v); __dfs(root->rs); }//debug int main(){ root = null; n=read<int>(); for(int i=1;i<=n;i++)li[i]=read<int>(),lst[i]=new node(li[i]); root = divide(1,n); int Q = read<int>(); while(Q--){ int op=__read_char(); switch(op){ case 1:Query();break; case 2:__insert();break; case 3:change();break; } } }