题目大意
给定一个非负整数序列{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 最大,输出最大是多少。
范围是3e5
分析
带区间的二进制trie,但是没有修改,只是在末尾加入,所以直接可持久化二进制trie贪心查找即可。
我也不知道为什么这么慢,但是我知道了递归和非递归时间差不多。
代码
递归和非递归都在里面了。
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=3e5+1005,N=24,maxv=maxn*2*N;
namespace IStream{
const int L=1<<15;
char buffer[L],*S,*T;
inline char Get_Char()
{
if(S==T)
{
T=(S=buffer)+fread(buffer,1,L,stdin);
if(S==T) return EOF;
}
return *S++;
}
inline void Rd(int &re)
{
char c;
re=0;
int k=1;
for(c=Get_Char();(c<'0'||c>'9') && c!='-';c=Get_Char());
if(c=='-')c=Get_Char(),k=-1;
while(c>='0'&&c<='9')
re=(re<<1)+(re<<3)+(c-'0'),c=Get_Char();
re*=k;
}
inline void Rd(char *s)
{
char c;
int len=0;
for(c=Get_Char();c<'A'||c>'z';c=Get_Char());
while(c!=' ' && c!='\n')
s[len++]=c,c=Get_Char();
}
int t[20],sz;
inline void outs(int x)
{
sz=0;
do{
t[++sz]=x%10;
x/=10;
}while(x);
for(int i=sz;i;i--)putchar(t[i]^48);
putchar('\n');
}
}
struct TRIE
{
int rt[maxv],np,ch[maxv][2],sz[maxv],val[maxv];
void Build()
{
np=1;
memset(rt,0,sizeof(rt));
memset(ch,0,sizeof(ch));
memset(sz,0,sizeof(sz));
memset(val,0,sizeof(val));
rt[0]=1;
}
int Newnode(int pre)
{
++np;
if(pre)
ch[np][0]=ch[pre][0],ch[np][1]=ch[pre][1],sz[np]=sz[pre],val[np]=val[pre];
else
ch[np][0]=ch[np][1]=sz[np]=val[np]=0;
return np;
}
void add(int pre,int &now,int x,int i)
{
now=Newnode(pre);
sz[now]++;
if(i>N)
{
val[now]++;
return;
}
bool id=x&(1<<(N-i));
add(ch[pre][id],ch[now][id],x,i+1);
}
void add(int x,int c)
{
//cout<<x<<endl;
int pre=rt[c-1];
int now=rt[c]=Newnode(pre);
for(int i=1;i<=N;i++)
{
bool id=x&(1<<(N-i));
ch[now][id]=Newnode(ch[pre][id]);
sz[ch[now][id]]++;
now=ch[now][id];
pre=ch[pre][id];
}
val[now]++;
}
int query(int lnow,int rnow,int x,int i)
{
if(i>N)return 0;
bool id=x&(1<<(N-i));
int ret;
if(sz[ch[rnow][id^1]]-sz[ch[lnow][id^1]])
{
ret=query(ch[lnow][id^1],ch[rnow][id^1],x,i+1);
ret=ret|(1<<(N-i));
}
else
{
ret=query(ch[lnow][id],ch[rnow][id],x,i+1);
ret=ret&(~(1<<(N-i)));
}
return ret;
}
int query(int x,int l,int r)
{
//cout<<x<<endl;
int lnow=rt[l],rnow=rt[r];
for(int i=1;i<=N;i++)
{
bool id=x&(1<<(N-i));
if(sz[ch[rnow][id^1]]-sz[ch[lnow][id^1]])
{
x=x|(1<<(N-i));
rnow=ch[rnow][id^1];
lnow=ch[lnow][id^1];
}
else
{
x=x&(~(1<<(N-i)));
rnow=ch[rnow][id];
lnow=ch[lnow][id];
}
}
return x;
}
}tri;
int n,m;
int sum[maxv];
char s[5];
void Init()
{
int x;
IStream::Rd(n);IStream::Rd(m);
tri.Build();
for(int i=1;i<=n;i++)
{
IStream::Rd(x);
sum[i]=sum[i-1]^x;
tri.add(tri.rt[i-1],tri.rt[i],sum[i-1],1);
}
}
void solve()
{
int x,l,r;
while(m--)
{
IStream::Rd(s);
if(s[0]=='A')
{
n++;
IStream::Rd(x);
sum[n]=sum[n-1]^x;
tri.add(tri.rt[n-1],tri.rt[n],sum[n-1],1);
}
else
{
IStream::Rd(l);IStream::Rd(r);IStream::Rd(x);
IStream::outs(tri.query(tri.rt[l-1],tri.rt[r],x^sum[n],1));
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
Init();
solve();
return 0;
}