再次写丑的我。。。(刚开始写了个线段树合并+fhq treap完TLE+MLE)
换成替罪羊+可持久化线段树合并之后随机数据1s+,不知道vfk搞得什么新闻,bzoj运行37s+
刚开始题意读错调了1h+我好菜
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define Sum(x) ((x)?(x)->sum:0)
#define Key(x) ((x)?(x)->key:0)
#define Size(x) ((x)?Sum(x->key):0)
#define L(x) ((x)?(x)->l:0)
#define R(x) ((x)?(x)->r:0)
#define maxn 105010
#define fac 0.7
#define MAX 70000
#define N 10000000
using namespace std;
namespace seg{
struct segment{
segment *l,*r;
int sum;
segment(){l=r=0,sum=0;}
void update(){sum=Sum(l)+Sum(r);}
void clear(){l=r=0,sum=0;}
}pool[N],*pp[N],**pm=pp;
typedef pair<segment*,segment*> data;
segment* merge(segment* a,segment* b,int l,int r){
if(!a&&!b)return 0;
segment* ptr=*(pm++);ptr->clear();
if(l==r){
ptr->sum=Sum(a)+Sum(b);
return ptr;
}
int mid=l+r>>1;
ptr->l=merge(L(a),L(b),l,mid);
ptr->r=merge(R(a),R(b),mid+1,r);
ptr->update();
return ptr;
}
int query(segment* a,int l,int r,int k){
if(!a||l==r)return 0;
int mid=l+r>>1;
if(k<=mid)return query(a->l,l,mid,k);
else return query(a->r,mid+1,r,k)+Sum(a->l);
}
void insert(segment*& a,int l,int r,int k){
if(!a)a=*(pm++),a->clear();
a->sum++;
if(l==r)return ;
int mid=l+r>>1;
if(k<=mid)insert(a->l,l,mid,k);
else insert(a->r,mid+1,r,k);
}
void _del(segment*& a,int l,int r,int k){
a->sum--;
if(l==r){if(Sum(a)==0)*--pm=a,a=0;return ;}
int mid=l+r>>1;
if(k<=mid)_del(a->l,l,mid,k);
else _del(a->r,mid+1,r,k);
a->update();
if(Sum(a)==0)*--pm=a,a=0;
}
void del(segment*& a){
if(!a)return ;
del(a->l);
del(a->r);
*--pm=a;a=0;
}
segment* newnode(int k){
segment* ptr=0;
insert(ptr,0,MAX,k);
return ptr;
}
void print(segment* a,int l,int r){
if(!a)return ;
if(l==r){
for(int i=1;i<=a->sum;++i)printf("%d ",l);
return ;
}
int mid=l+r>>1;
print(a->l,l,mid);
print(a->r,mid+1,r);
}
};
struct gtree{
gtree *l,*r;
seg::segment *key;
int pkey,sum;
void init(int pkey){
this->pkey=pkey;
sum=1,l=r=0;
}
void update(){sum=1+Sum(l)+Sum(r);}
}pool[N],*pp[N],**pm=pp,*root,*inv[maxn];
int ptr,a[maxn],b[maxn];
void del(gtree*& g){
if(!g)return ;
del(g->l);
a[++ptr]=g->pkey;
del(g->r);
seg::del(g->key);
*--pm=g;
}
void build(gtree*& g,int l,int r){
if(l>r)return ;
int mid=l+r>>1;
g=*(pm++),g->init(a[mid]);
build(g->l,l,mid-1);
build(g->r,mid+1,r);
g->key=seg::merge(Key(g->l),Key(g->r),0,MAX);
seg::insert(g->key,0,MAX,g->pkey);
g->update();
}
void rebuild(gtree*& g){
ptr=0,del(g),build(g,1,ptr);
}
void insert(gtree*& g,int k,int key){
if(!g){g=*(pm++),g->init(key);seg::insert(g->key,0,MAX,g->pkey);return ;}
g->sum++,seg::insert(g->key,0,MAX,key);
// int a;printf("[%d,%d,%d,%d]",a=rand(),g,g->l,g->r);
// printf("[%d,%d]",k,key);
if(Sum(g->l)>=k)insert(g->l,k,key);
else insert(g->r,k-Sum(g->l)-1,key);
// printf("[%d,%d]\n",a,g);
}
void check(gtree*& g,int k){
if(!g)return ;
if(max(Sum(g->l),Sum(g->r))>Sum(g)*fac)
{rebuild(g);return ;}
if(Sum(g->l)>=k)check(g->l,k);
else check(g->r,k-Sum(g->l)-1);
}
int modify(gtree*& g,int k,int key){
int a;
if(k==Sum(g->l)+1){
seg::_del(g->key,0,MAX,g->pkey);
seg::insert(g->key,0,MAX,key);
a=g->pkey,g->pkey=key;
return a;
}
if(Sum(g->l)>=k)a=modify(g->l,k,key);
else a=modify(g->r,k-Sum(g->l)-1,key);
seg::_del(g->key,0,MAX,a);
seg::insert(g->key,0,MAX,key);
return a;
}
void getinv(gtree*& root,int l,int r){
// printf("[%d,%d]",l,r);
if(l>r||!root)return ;
int lsum=Sum(root->l);
if(l==1&&Sum(root)==r){inv[++ptr]=root;return ;}
if(l<=lsum+1&&lsum+1<=r){inv[++ptr]=0,b[ptr]=root->pkey;}
if(lsum>=r)getinv(root->l,l,r);
else if(l>lsum+1)getinv(root->r,l-lsum-1,r-lsum-1);
else getinv(root->l,l,lsum),getinv(root->r,1,r-lsum-1);
}
void dfs(gtree*& root){
if(!root)return ;
dfs(root->l);
// fprintf(stderr,"%d ",root->pkey);
dfs(root->r);
}
int query(gtree*& root,int l,int r,int k){
ptr=0,getinv(root,l,r);
l=0,r=MAX;
while(l<r){
int mid=l+r+1>>1;
int ans=0;
for(int i=1;i<=ptr;++i){
if(!inv[i])ans+=mid>b[i];
else ans+=seg::query(inv[i]->key,0,MAX,mid);
}
// printf("[%d,%d,%d]\n",ans,l,r);
if(ans>=k)r=mid-1;
else l=mid;
}
return l;
}
#define DEBUG
int n,q,lst;
int main(){
#ifdef DEBUG
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
// freopen("err.txt","w",stderr);
for(int i=0;i<N;++i)seg::pp[i]=seg::pool+i;
for(int i=0;i<N;++i)pp[i]=pool+i;
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%d",&a[i]);
build(root,1,n);
scanf("%d",&q);
for(int i=1,x,y,k;i<=q;++i){
#ifdef DEBUG
lst=0;
#endif
// seg::print(root->key,0,MAX);puts("");
// dfs(root);fprintf(stderr,"\n");
char op[2];scanf("%s%d%d",op,&x,&y);
// fprintf(stderr,"%s %d %d\n",op,x,y);
x^=lst,y^=lst;
// printf("[Real:%d,%d]",x,y);
if(op[0]=='Q'){
// if(x==8&&y==8)return 0;
scanf("%d",&k),k^=lst;
printf("%d\n",lst=query(root,x,y,k));
} else if(op[0]=='M'){
modify(root,x,y);
} else insert(root,x-1,y),check(root,x-1);
}
}