P4735 最大异或和

Posted Jozky86

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4735 最大异或和相关的知识,希望对你有一定的参考价值。

P4735 最大异或和

题意:

一个非负序列a,初始长度为n,有两种操作:

  1. A x,在序列中添加x,n加一
  2. 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[p1])
相当于我们巧妙的将后缀问题转换成前缀问题,那就是找一个前缀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 最大异或和的主要内容,如果未能解决你的问题,请参考以下文章

P4735 最大异或和

洛谷P4735 最大异或和

P4735 最大异或和

[P4735] 最大异或和 - 可持久化Trie

[Luogu P4735]最大异或和(可持久化Trie)

可持久化Trie树