BZOJ 3261: 最大异或和 可持久化字典树
2017-07-24 11:45
399 查看
3261: 最大异或和
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1906 Solved: 789
[Submit][Status][Discuss]
Description
给定一个非负整数序列 {a},初始长度为 N。有M个操作,有以下两种操作类型:
1 、A x:添加操作,表示在序列末尾添加一个数 x,序列的长度 N+1。
2 、Q l r x:询问操作,你需要找到一个位置 p,满足 l<=p<=r,使得:
a[p] xor a[p+1] xor ... xor a
xor x 最大,输出最大是多少。
Input
第一行包含两个整数N,M,含义如问题描述所示。第二行包含 N个非负整数,表示初始的序列 A 。
接下来 M行,每行描述一个操作,格式如题面所述。
Output
假设询问操作有 T个,则输出应该有 T行,每行一个整数表示询问的答案。Sample Input
5 52 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保证没有修改操作。
对于 100% 的数据,0<=a[i]<=10^7。
Sample Output
45
6
HINT
对于100% 的数据,0<=a[i]<=10^7 。可持久化字典树 看名字都很高级
前一阵l1ll5讲过 前一阵写了一写。。。拖到今天才写blog
没怎么看代码 自己YY了一个和主席树写法差不多的东西
正规写法 以后学一学
说题解:
我们要在给定区间 [l,r] 选择一个 a[p] 使得对于给定的 x
有 a[p] xor a[p+1] xor ... xor a
xor x 最大
并且支持在末尾插入数 x 令数列变长
对于这个问题 不想插入、异或相关 脑袋里应该先蹦出来主席树
对于异或的处理,可以看这个求数列中两数异或合最大值 最富有的人 trie树贪心
括弧: 当然 你要说线性基来搞这个 我只能%%%
这时考虑:
对于 a[p] xor a[p+1] xor ... xor a
(1)
维护b[i]=a[1] xor a[2] xor ... xor a[i]
则 (1) 可表示为 b
xor b[p-1] (2)
所以原式可表示为 (2) xor x
即 b[p-1] xor ( b
xor x)
所以对于查询区间 [l,r] 就是主席树的 [root[l-2],root[r-1]]
插入的时候就正常搞前缀和 硬往里插就好了
狂WA7发
让我回想遥远的记忆 看看能为后人留下什么要注意的细节
WA的前两发大概是这样的:
查询[l,r]想传参到函数里再搞,结果忘了。。
后几发都是root[l-2],root[r-1]都搞到root[0]结果鬼畜挂掉
#include<cmath> #include<ctime> #include<cstdio> #include<cstring> #include<cstdlib> #include<complex> #include<iostream> #include<algorithm> #include<iomanip> #include<vector> #include<bitset> #include<string> #include<queue> #include<map> #include<set> using namespace std; typedef double db; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return f*x; } inline void print(int x) {if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');} const int N=600100; struct trie{int ls,rs,sz;}tr[N<<5]; int n,cnt,a ,root ,bin[30]; void insert(int &k,int x,int pos,int num) { k=++cnt;tr[k].sz=tr[x].sz+1;if(pos<0)return ; if(num&bin[pos]){tr[k].ls=tr[x].ls;insert(tr[k].rs,tr[x].rs,pos-1,num);} else{tr[k].rs=tr[x].rs;insert(tr[k].ls,tr[x].ls,pos-1,num);} } inline void add(int x) { a[++n]=a[n-1]^x; insert(root ,root[n-1],25,a ); } inline void query(int x,int y,int val) { register int pos=25,l=root[x],r=root[y],res=0; if(x==y)res=a[x]^val; while(~pos) { if(val&bin[pos]) { if(tr[tr[r].ls].sz-tr[tr[l].ls].sz) {l=tr[l].ls;r=tr[r].ls;res|=bin[pos];} else l=tr[l].rs,r=tr[r].rs; } else { if(tr[tr[r].rs].sz-tr[tr[l].rs].sz) {l=tr[l].rs;r=tr[r].rs;res|=bin[pos];} else l=tr[l].ls,r=tr[r].ls; } pos--; } print(res);puts(""); } int main() { n=read();int Q=read(); register int i,l,r,x; for(i=1;i<=n;++i)a[i]=read()^a[i-1]; for(i=0;i<29;++i)bin[i]=1<<i; for(i=1;i<=n;++i){insert(root[i],root[i-1],25,a[i]);} char ch[2]; while(Q--){scanf("%s",ch);ch[0]=='A'?(x=read(),add(x)):(l=read(),r=read(),x=read(),query(max(0,l-2),r-1,a ^x));} return 0; } /* 5 5 2 6 4 3 6 A 1 Q 3 5 4 A 4 Q 5 7 0 Q 3 6 6 4 5 6 */
相关文章推荐
- [BZOJ 3261]最大异或和:可持久化字典树
- bzoj 3261最大异或和 可持久化字典树
- bzoj 3261: 最大异或和 可持久化字典树
- [可持久化字典树] BZOJ 3261 最大异或和
- BZOJ 3261: 最大异或和|可持久化Tire树
- BZOJ 3261: 最大异或和( 可持久化trie )
- BZOJ 3261: 最大异或和 [可持久化Trie]
- [BZOJ3261][最大异或和][可持久化Trie]
- [BZOJ]3261: 最大异或和 可持久化Trie
- BZOJ 3261 最大异或和 可持久化Trie
- BZOJ 3261 最大异或和 可持久化Trie树
- 【bzoj3261】【最大异或和】可持久化trie树+贪心
- BZOJ 3261 最大异或和 可持久化Trie
- bzoj 3261: 最大异或和 可持久化Trie
- 【bzoj 3261】最大异或和(可持久化Trie树)
- [bzoj3261][可持久化Tire]最大异或和
- BZOJ 3261 最大异或和 && qwb VS 去污棒(可持久化01Trie)
- bzoj 3261: 最大异或和 (可持久化trie树)
- BZOJ_3261_最大异或和_可持久化trie
- bzoj 3261 最大异或和【可持久化trie】