题解: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;
}

浙公网安备 33010602011771号