http://www.elijahqi.win/archives/3261
Description
给定一个非负整数序列{a},初始长度为N。
有M个操作,有以下两种操作类型:
1、Ax:添加操作,表示在序列末尾添加一个数x,序列的长度N+1。
2、Qlrx:询问操作,你需要找到一个位置p,满足l<=p<=r,使得:
a[p] xor a[p+1] xor … xor a[N] xor x 最大,输出最大是多少。
Input
第一行包含两个整数 N ,M,含义如问题描述所示。
第二行包含 N个非负整数,表示初始的序列 A 。
接下来 M行,每行描述一个操作,格式如题面所述。
Output
假设询问操作有 T个,则输出应该有 T行,每行一个整数表示询问的答案。
Sample Input
5 5
2 6 4 3 6
A 1
Q 3 5 4
A 4
Q 5 7 0
Q 3 6 6
对于测试点 1-2,N,M<=5 。
对于测试点 3-7,N,M<=80000 。
对于测试点 8-10,N,M<=300000 。
其中测试点 1, 3, 5, 7, 9保证没有修改操作。
0<=a[i]<=10^7。
Sample Output
4
5
6
HINT
Source
可持久化trie树
类比主席树 考虑 异或的性质 sum[l~n]=sum[n]^sum[l-1] 那么原题转化一下求x^sum[n]在l-2~r-1的trie树上贪心即可 为了防止re 首先在开头插入一个0 那么每次询问的时候恰好就是l-1~r即可 每个节点记录 出现了几次 每次在trie树上往相反方向走即可
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S) {T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
while(isdigit(ch)) x=x*10+ch-'0',ch=gc();
return x*f;
}
const int N=600030;
struct node{
int sum[2],ch[2];
}tree[20000010];
int num,n,m,rt[N],bin[30],ans,sum[N];
inline void init(int &x){tree[++num]=tree[x];x=num;}
inline void insert1(int &x,int v){
init(x);int p=x;
for (int i=24;~i;--i){
int op=(v&bin[i])>0;
++tree[p].sum[op];init(tree[p].ch[op]);
p=tree[p].ch[op];
}
}
inline void query(int rt1,int rt2,int v){
for (int i=24;~i;--i){
int op=(v&bin[i])>0;
if (tree[rt2].sum[op^1]-tree[rt1].sum[op^1]){
ans+=bin[i];rt1=tree[rt1].ch[op^1];rt2=tree[rt2].ch[op^1];
}else{
rt1=tree[rt1].ch[op];rt2=tree[rt2].ch[op];
}
}
}
int main(){
freopen("bzoj3261.in","r",stdin);
n=read();m=read();
for (int i=0;i<=24;++i) bin[i]=1<<i;
insert1(rt[1],0);++n;
for (int i=2;i<=n;++i) sum[i]=read(),rt[i]=rt[i-1],
insert1(rt[i],(sum[i]^=sum[i-1]));
for (int i=1;i<=m;++i){
char op=gc();while(op!='A'&&op!='Q') op=gc();
if(op=='A'){
sum[n+1]=read();sum[n+1]^=sum[n];rt[n+1]=rt[n];++n;
insert1(rt[n],sum[n]);//printf("%ddfs\n",sum[n]);
}else{
int l=read(),r=read(),x=read()^sum[n];ans=0;
query(rt[l-1],rt[r],x);printf("%d\n",ans);
}
}
return 0;
}