题解:CF1847C Vampiric Powers, anyone?

思路分析

我们可以先手玩一下选一次,选两次和选三次的情况。

设第一次选择了 \(x\),则 \(a_{n+1}=a_x \oplus a_{x+1} \oplus \dots \oplus a_n\)

设第二次选择了 \(y\),分类讨论一下。

  • 假如 \(y<x\),则 \(a_{n+2}=a_y \oplus a_{y+1} \oplus \dots \oplus a_n \oplus a_{n+1}=a_y \oplus a_{y+1} \oplus \dots \oplus a_{x-1}\)

  • 假如 \(y>x\),则 \(a_{n+2}=a_y \oplus a_{y+1} \oplus \dots \oplus a_n \oplus a_{n+1}=a_x \oplus a_{x+1} \oplus \dots \oplus a_{y-1}\)。发现 \(y>x\) 的情况与先选 \(y\) 后选 \(x\) 等价,所以不妨设先选了 \(x\),后选了 \(y\),且 \(y<x\)。此时 \(a_{n+1} \oplus a_{n+2} = a_y \oplus a_{y+1} \oplus \dots \oplus a_n\),相当于只选了一个 \(y\)

设第三次选择了 \(z\),分类讨论。

  • \(z<y\),则 \(a_{n+3}=a_z \oplus a_{z+1} \oplus \dots \oplus a_{y-1}\),此时与先选 \(z\) 再选 \(y\) 等价。

  • \(y<z<x\),则 \(a_{n+3}=a_y \oplus a_{y+1} \oplus \dots \oplus a_{z-1}\),此时与先选 \(y\),后选 \(z\) 等价。

  • \(x<z\),则 \(a_{n+3}=a_y \oplus a_{y+1} \oplus \dots \oplus a_{z-1}\),此时与先选 \(y\),后选 \(z\) 等价。

发现无论如何,都相当 \(a_{n+1}\) 与只选 \(y\)\(z\) 等价,而此时 \(a_{n+1} \oplus a_{n+2} \oplus a_{n+3} = a_z \oplus a_{z+1} \oplus \dots \oplus a_n\),等价于只选了一个 \(z\)

继而可以推出选四个的时候相当于只选了第四个与当前的 \(z\),第五个第六个等也同理。而此时新增加的一定是原数组中的一段区间的异或值。所以我们只需要找到原数组中最大区间异或值就行了,这是不难解决的,可以用前缀异或和字典树来做。

AcCode

#include <bits/stdc++.h>
using namespace std;
#define int long long

const int N=1e5+10;

int n,idx;
int a[N];
int tr[N*15][2];

inline int read(){
	int t=0,f=1;
	register char c=getchar();
	while (c<48||c>57) f=(c=='-')?(-1):(f),c=getchar();
	while (c>=48&&c<=57)t=(t<<1)+(t<<3)+(c^48),c=getchar();
	return f*t;
}

void solution(){
	/*
        设第一次从 a_x 开始,则 a_n+1=a_x^...^a_n
		第二次从 a_y 开始
		1.y<x 则 a_n+2=a_y^...^a_x-1
		2.y>x 则 a_n+2=a_x^...^a_y-1
		第二种情况与先选 y 后选 x 一致
		所以设两次 y<x
		第三次为 z
		1.z<y a_n+3=a_n+1^a_n+2 ^ a_y^...^a_n ^ a_z^...^a_y-1
		=a_z^...^a_y-1
		此时与先选 y 再选 z 情况一致
		2.y<z<x a_n+3=a_n+1^a_n+2 ^ a_x^...^a_n ^ a_z^...^a_x-1
		=a_n+2 ^ a_z^...^a_x-1
		=a_y^...^a_z-1
		此时与先选 z 后选 y 一致
		3.x<z a_n+3=a_n+1^a_n+2 ^ a_z^...^a_n
		=a_y^...^a_z-1
		此时与先选 z 后选 y 一致
		
		所以问题就是选出一段区间,使其异或值最大
		
		8 2 4 12 1
		1000
		0010
		0100
		1100
		0001
		
		1110=14
	*/
}

void insert(int x){
	int rt=0;
	for(int i=10;i>=0;i--){
		int d=(x>>i)&1;
		if(!tr[rt][d]) tr[rt][d]=++idx;
		rt=tr[rt][d];
	}
}

int query(int x){
	int rt=0,sum=0;
	for(int i=10;i>=0;i--){
		int d=(x>>i)&1;
		if(tr[rt][(!d)]) rt=tr[rt][(!d)],sum+=(1<<i);
		else rt=tr[rt][d];
	}
	return sum;
}

signed main(){
	int T=read();
	while(T--){
		n=read();idx=0;
		for(int i=1;i<=n;i++) a[i]=read(),a[i]^=a[i-1];
		insert(0); 
		int ans=0;
		for(int i=1;i<=n;i++){
			ans=max(ans,query(a[i]));
			insert(a[i]);
		}
		cout<<ans<<"\n";
		for(int i=0;i<=idx;i++) tr[i][0]=tr[i][1]=0; 
	}	
	return 0;
}

posted @ 2025-03-27 10:09  ask_silently  阅读(8)  评论(0)    收藏  举报