[bzoj3261]最大异或和(可持久化trie)
题目大意:
给定一个非负整数序列{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 最大,输出最大是多少。
解题关键:可持久化trie模板题。
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> using namespace std; typedef long long ll; #define N 600005 int n,m; int a[N],sum[N],root[N]; struct trie{ int cnt; int ch[N*25][2],num[N*25],bin[30]; void init(){ bin[0]=1;for(int i=1;i<30;i++)bin[i]=bin[i-1]<<1;} int insert(int x,int val){ int tmp,y;tmp=y=++cnt; for(int i=23;i>=0;i--){ ch[y][0]=ch[x][0];ch[y][1]=ch[x][1]; num[y]=num[x]+1; int t=(val&bin[i])>>i; x=ch[x][t]; ch[y][t]=++cnt; y=ch[y][t]; } num[y]=num[x]+1; return tmp; } int query(int l,int r,int val){ int tmp=0; for(int i=23;i>=0;i--){ int t=(val&bin[i])>>i; if(num[ch[r][t^1]]-num[ch[l][t^1]]) tmp+=bin[i],r=ch[r][t^1],l=ch[l][t^1]; else r=ch[r][t],l=ch[l][t]; } return tmp; } }trie; int main(){ trie.init(); scanf("%d%d",&n,&m); n++; for(int i=2;i<=n;i++)scanf("%d",a+i); for(int i=1;i<=n;i++)sum[i]=sum[i-1]^a[i];//异或前缀和 for(int i=1;i<=n;i++)root[i]=trie.insert(root[i-1],sum[i]); char ch[5]; int l,r,x; while(m--){ scanf("%s",ch); if(ch[0]=='A'){ n++; scanf("%d",&a[n]);sum[n]=sum[n-1]^a[n]; root[n]=trie.insert(root[n-1],sum[n]); } else{ scanf("%d%d%d",&l,&r,&x); printf("%d\n",trie.query(root[l-1],root[r],sum[n]^x)); } } return 0; }