import java.io.*;
import java.util.*;
public class Main {
static int N = 200010, M = 21 * N;
static int son[][] = new int[M][2], idx;
// l[i]表示从 i到n 范围内异或和子段的最大/最小值
static int lmin[] = new int[N], lmax[] = new int[N];
// r[i]表示从 1到i 范围内异或和子段的最大/最小值
static int rmin[] = new int[N], rmax[] = new int[N];
static int a[] = new int[N];
static int n;
/*
a^b^b = a
所以对于区间也是如此:
比如: 在计算rmin[]和rmax[]时, 当枚举到k时
sum是一段连续的区间异或和: a[1]^a[2]...^a[k],
每次query_min(sum)时, 因为trie里面存的是每个从1到k的区间异或和:[1-3], [1-6]...
比如 sum ^ [1-3] = [4-k],
所以每次异或后求得的最小值即为区间1到k中的某个字段的异或和,
求一下前缀, 求一下后缀, 最后计算一下, 就能覆盖所有的情况
*/
public static void insert(int x){
int p = 0;
for(int i = 20; i >= 0; i--){
int u = x >> i & 1;
if(son[p][u] == 0) son[p][u] = ++idx;
p = son[p][u];
}
}
public static int query_min(int x){
int p = 0, res = 0;
for(int i = 20; i >= 0; i--){
int u = x >> i & 1;
if(son[p][u] != 0){
p = son[p][u];
}else{
p = son[p][u ^ 1];
res |= 1 << i;
}
}
return res;
}
public static int query_max(int x){
int p = 0, res = 0;
for(int i = 20; i >= 0; i--){
int u = x >> i & 1;
if(son[p][u ^ 1] != 0){
p = son[p][u ^ 1];
res |= 1 << i;
}else {
p = son[p][u];
}
}
return res;
}
public static void solve(){
// 计算前缀1-r
int sum = 0;
rmin[0] = (int)2e9;
rmax[0] = -1;
insert(0);
for(int i = 1; i <= n; i++){
sum ^= a[i];
rmin[i] = Math.min(rmin[i - 1], query_min(sum));
rmax[i] = Math.max(rmax[i - 1], query_max(sum));
insert(sum);
}
for(int i = 0; i < M; i++) Arrays.fill(son[i], 0);
idx = 0;
// 计算后缀l-n
sum = 0;
lmin[n + 1] = (int)2e9;
lmax[n + 1] = -1;
insert(0);
for(int i = n; i >= 1; i--){
sum ^= a[i];
lmin[i] = Math.min(lmin[i + 1], query_min(sum));
lmax[i] = Math.max(lmax[i + 1], query_max(sum));
insert(sum);
}
int ans = 0;
for(int i = 1; i < n; i++){
ans = Math.max(ans, Math.max(lmax[i + 1] - rmin[i], rmax[i] - lmin[i + 1]));
}
System.out.println(ans);
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer stmInput = new StreamTokenizer(br);
stmInput.nextToken();
n = (int)stmInput.nval;
for(int i = 1; i <= n; i++){
stmInput.nextToken();
a[i] = (int)stmInput.nval;
}
solve();
br.close();
}
}
异或和之差
最新推荐文章于 2024-07-14 22:26:46 发布