P4735 最大异或和
Posted dreagonm
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4735 最大异或和相关的知识,希望对你有一定的参考价值。
思路
可持久化Trie树的好题
注意到题目要求求的询问非常的鬼,不太好做
然后有趣的思路就出现了,我们预处理出来异或前缀和s[i],每次询问的x异或上s[n]之后,问题就变成了在l-1~r-1中选一个异或x最大的数
然后因为区间查询,上可持久化Trie树就好了
注意初始的Trie树不能是空树,必须先插入一个节点
代码
洛谷上说这题卡常?不过我一发压着时限跑过去了233
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXlen = 30;
const int MAXN = 300100*2;
int s[MAXN],root[MAXN],Nodecnt=0,n,m;
struct Node{
int son[2],sz;
}trie[MAXN*30];
void insert(int val,int &o,int d){
trie[++Nodecnt]=trie[o];
o=Nodecnt;
trie[o].sz++;
if(d>=0)
insert(val,trie[o].son[(val>>d)&1],d-1);
}
int query(int lroot,int rroot,int val,int d){
if(d<0)
return 0;
int f=(val>>d)&1;
if(trie[trie[rroot].son[!f]].sz>trie[trie[lroot].son[!f]].sz)
return (1<<d)+query(trie[lroot].son[!f],trie[rroot].son[!f],val,d-1);
else
return query(trie[lroot].son[f],trie[rroot].son[f],val,d-1);
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&s[i]);
for(int i=1;i<=n;i++)
s[i]=s[i-1]^s[i];
insert(s[0],root[0],MAXlen);
for(int i=1;i<=n;i++){
root[i]=root[i-1];
insert(s[i],root[i],MAXlen);
}
for(int i=1;i<=m;i++){
char c=getchar();
while(c!='A'&&c!='Q')
c=getchar();
if(c=='Q'){
int l,r,x;
scanf("%d %d %d",&l,&r,&x);
l--;
r--;
x^=s[n];
int req;
if(l==0)
req=query(0,root[r],x,MAXlen);
else
req=query(root[l-1],root[r],x,MAXlen);
printf("%d
",req);
}
else{
int x;
scanf("%d",&x);
n++;
s[n]=s[n-1]^x;
root[n]=root[n-1];
insert(s[n],root[n],MAXlen);
}
}
return 0;
}
以上是关于P4735 最大异或和的主要内容,如果未能解决你的问题,请参考以下文章