P4735 最大异或和
Posted Jozky86
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4735 最大异或和相关的知识,希望对你有一定的参考价值。
题意:
一个非负序列a,初始长度为n,有两种操作:
- A x,在序列中添加x,n加一
- Q l r x,询问操作,询问一个位置p,p满足l<=p<=r,使得p到位置n的的异或和与x的异或值最大,输出最大值
题解:
我们来看这个查询操作,p∈[l,r],我们设整个区间的异或值为tot,
a
[
p
]
⊕
a
[
p
+
1
]
⊕
.
.
.
.
.
a
[
N
]
a[p] ⊕ a[p+1] ⊕ .....a[N]
a[p]⊕a[p+1]⊕.....a[N]=
t
o
t
⊕
(
a
[
1
]
⊕
a
[
2
]
.
.
.
.
.
⊕
a
[
p
−
1
]
)
tot ⊕ (a[1] ⊕ a[2].....⊕a[p-1])
tot⊕(a[1]⊕a[2].....⊕a[p−1])
相当于我们巧妙的将后缀问题转换成前缀问题,那就是找一个前缀s[y]⊕(x⊕tot)的值最大,y属于[l-1,r-1]。转化成可持久化01Trie经典模型:
给定(l,r,x),在序列[l,r]区间中选一个数a[i],使得a[i]⊕x最大
然后按照可持久化的套路,我们将所有前缀异或和s[i]建立可持久化01Trie,算出(x⊕tot)的值后在rt[l-2]到rt[r-1]这两颗树上走一边,寻找最大值
代码:
#include<bits/stdc++.h>
#define debug(a,b) printf("%s = %d\\n",a,b);
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
//Fe~Jozky
const ll INF_ll=1e18;
const int INF_int=0x3f3f3f3f;
inline ll read(){
ll s=0,w=1ll;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1ll;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10ll+((ch-'0')*1ll),ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);
return s*w;
}
void rd_txt(){
#ifdef ONLINE_JUDGE
#else
freopen("in.txt","r",stdin);
#endif
}
const int maxn=6e5+9;
struct tree{
int cnt;
int ch[2];
}tr[maxn*30];
int rtnum=0;
int a[maxn];
int rt[maxn];
int tot=0;
void insert(int now,int pre,int x){
for(int i=30;i>=0;i--){
int c=((x>>i)&1);
tr[now].ch[c^1]=tr[pre].ch[c^1];
tr[now].ch[c]=++rtnum;
now=tr[now].ch[c];
pre=tr[pre].ch[c];
tr[now].cnt=tr[pre].cnt+1;
}
}
int get(int L,int R,int x){
int sum=0;
for(int i=30;i>=0;i--){
int c=((x>>i)&1);
if(tr[tr[R].ch[c^1]].cnt>tr[tr[L].ch[c^1]].cnt){
sum+=(1<<i);
L=tr[L].ch[c^1];
R=tr[R].ch[c^1];
}
else {
L=tr[L].ch[c];
R=tr[R].ch[c];
}
}
return sum;
}
int main()
{
rd_txt();
int n,m;
cin>>n>>m;
rt[0]=++rtnum;
insert(rt[0],0,0);
tot=0;
for(int i=1;i<=n;i++){
cin>>a[i];
tot^=a[i];
rt[i]=++rtnum;
insert(rt[i],rt[i-1],tot);
}
for(int i=1;i<=m;i++){
string op;
cin>>op;
int x;
if(op=="A")
{
cin>>x;
tot^=x;
rt[++n]=++rtnum;
insert(rt[n],rt[n-1],tot);
}
else if(op=="Q"){
int l,r,x;
cin>>l>>r>>x;
l--;r--;
if(l==0)printf("%d\\n",get(0,rt[r],tot^x));
else printf("%d\\n",get(rt[l-1],rt[r],tot^x));
}
}
return 0;
}
以上是关于P4735 最大异或和的主要内容,如果未能解决你的问题,请参考以下文章