您的位置:首页 > 产品设计 > UI/UE

Codechef Xor Queries(可持久化字典树)

2016-10-11 20:38 399 查看
题意:

给定一个初始时为空的整数序列(元素由1开始标号)以及一些询问:

类型0:在数组最后加入数字x

类型1:在区间[L,R]中找到数字y,最大化(x^y)

类型2:删除数组最后k个元素

类型3:在区间[L,R]中,统计小于等于x的元素个数

类型4:在区间[L,R]中,找到第k小的数

(M<=5e5,x<=5e5)

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=5e5+100;

struct Trie{
int ch[2],sum,dep;
}T[N*30];
int root
,sz;

void insert(int &i,int d,int x,int v){
T[++sz]=T[i],i=sz;
T[i].dep=d+1;
T[i].sum+=v;    //此时判断的是上一位的d
if(d<0) return ;
int p=(x>>d)&1;
insert(T[i].ch[p],d-1,x,v);
}

void Query_max_xor(int L,int R,int d,int x,int &ans){
if(d<0)     return ;
int p=(x>>d)&1;
if(T[ T[R].ch[p^1] ].sum-T[ T[L].ch[p^1] ].sum)
ans+=(p^1)*(1<<d),Query_max_xor(T[L].ch[p^1],T[R].ch[p^1],d-1,x,ans);
else    ans+=p*(1<<d),Query_max_xor(T[L].ch[p],T[R].ch[p],d-1,x,ans);
}

void Query_equal_to_x(int L,int R,int d,int x,int &ans){
if(d<0)     {ans+=T[R].sum-T[L].sum;return ;}
int p=(x>>d)&1;
if(p==1)  ans+=T[ T[R].ch[0] ].sum-T[ T[L].ch[0] ].sum;
Query_equal_to_x(T[L].ch[p],T[R].ch[p],d-1,x-p*(1<<d),ans);
}

void Query_kth(int L,int R,int d,int x,int &ans){
if(d<0)     return ;
int k=T[ T[R].ch[0] ].sum-T[ T[L].ch[0] ].sum;
if(k>=x)    Query_kth(T[L].ch[0],T[R].ch[0],d-1,x,ans);
else   ans+=(1<<d),Query_kth(T[L].ch[1],T[R].ch[1],d-1,x-k,ans);
}

int main(){
int m,n=0,L,R,ans,op,x;
while(scanf("%d",&m)!=EOF){
sz=0,root[0]=0;
while(m--){
scanf("%d",&op);
if(op==0){
scanf("%d",&x);
root[++n]=root[n-1];
insert(root
,23,x,1);
}
else if(op==1){
scanf("%d%d%d",&L,&R,&x);
Query_max_xor(root[L-1],root[R],23,x,ans=0);
printf("%d\n",ans);
}
else if(op==2)
scanf("%d",&x),n-=x;
else if(op==3){
scanf("%d%d%d",&L,&R,&x);
Query_equal_to_x(root[L-1],root[R],23,x,ans=0);
printf("%d\n",ans);
}
else if(op==4){
scanf("%d%d%d",&L,&R,&x);
Query_kth(root[L-1],root[R],23,x,ans=0);
printf("%d\n",ans);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: