题目大意: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\n",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;
}
}
}