BZOJ3261: 最大异或和
【传送门:BZOJ3261】
简要题意:
给出n个数,有m个操作,有两种操作:
A x在序列末尾添加一个数x,序列长度+1
Q l r x在l到r中选出一个位置q,使得a[p]^a[p+1]^... ^a[n]^x最大,求出这个最大值
题解:
可持久化01字典树的例题
其实建图和查找都和主席树差不多,而找最大值的时候贪心找就可以了
参考代码:
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<cstring> using namespace std; struct trie { int son[2],c; }tr[15000000];int trlen; int rt[15000000]; void Link(int &u1,int v,int d) { if(u1==0) u1=++trlen; tr[u1].c++; if(d<0) return ; int p=(v>>d)&1; Link(tr[u1].son[p],v,d-1); } void Merge(int &u1,int u2) { if(u1==0){u1=u2;return ;} if(u2==0) return ; tr[u1].c+=tr[u2].c; Merge(tr[u1].son[0],tr[u2].son[0]); Merge(tr[u1].son[1],tr[u2].son[1]); } int query(int x,int y,int v,int d) { if(d<0) return 0; int p=(v>>d)&1; int tmp=tr[tr[x].son[p^1]].c-tr[tr[y].son[p^1]].c; if(tmp>0) return (1<<d)+query(tr[x].son[p^1],tr[y].son[p^1],v,d-1); else return query(tr[x].son[p],tr[y].son[p],v,d-1); } int main() { int n,m; scanf("%d%d",&n,&m);n++; trlen=0; Link(rt[1],0,24); int tot=0; for(int i=2;i<=n;i++) { int d; scanf("%d",&d);tot^=d; Link(rt[i],tot,24); Merge(rt[i],rt[i-1]); } char st[5]; while(m--) { scanf("%s",st+1); if(st[1]=='A') { int d; scanf("%d",&d);tot^=d; n++; Link(rt[n],tot,24); Merge(rt[n],rt[n-1]); } else { int x,y,k; scanf("%d%d%d",&x,&y,&k); printf("%d\n",query(rt[y],rt[x-1],tot^k,24)); } } return 0; }
渺渺时空,茫茫人海,与君相遇,幸甚幸甚