1 条题解
-
1
int sum[MAXN + 5];
:前缀异或和,sum[r]^sum[l-1]
为a[l]~a[r]
的异或和。int f[MAXN + 5];
:f[i]
为a[1]~a[i]
所有子区间异或和中的最大值。f[i] = max(f[i-1],以a[i]结尾的子区间的异或和最大值)
- 以
a[i]
结尾的子区间的异或和最大值:看看sum[0]~sum[i-1]
哪个和sum[i]
异或一下最大。
#include <bits/stdc++.h> using namespace std; const int MAXNODE = 400000 * 31; // 单词数*单词长度(最坏情况下节点数量) int tot, root, son[MAXNODE + 5][2]; int tag[MAXNODE + 5]; // 存在几个单词 void clearNode(int nId) { for (int i = 0; i < 2; i++) son[nId][i] = 0; tag[nId] = 0; } void ins(int s) { int now = root; for (int i = 30; i >= 0; i--) { // s的2^i位是多少 int j = ((s >> i) & 1); if (!son[now][j]) { son[now][j] = ++tot; clearNode(tot); } now = son[now][j]; } } int check(int s) { int res = 0; int now = root; for (int i = 30; i >= 0; i--) { int j = ((s >> i) & 1); // 尽可能走不同的 if (son[now][1 - j]) { res += (1 << i); now = son[now][1 - j]; } else { now = son[now][j]; } } return res; } const int MAXN = 400000; int n; int a[MAXN + 5]; int sum[MAXN + 5]; int f[MAXN + 5]; int g[MAXN + 5]; int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n; for (int i = 1; i <= n; i++) cin >> a[i]; // cal f[] tot = root = 1; clearNode(tot); sum[1] = a[1]; for (int i = 2; i <= n; i++) sum[i] = sum[i - 1] ^ a[i]; ins(0); f[0] = 0; for (int i = 1; i <= n; i++) { f[i] = max(f[i - 1], check(sum[i])); ins(sum[i]); } // cal g[] tot = root = 1; clearNode(tot); sum[n] = a[n]; for (int i = n - 1; i >= 1; i--) sum[i] = sum[i + 1] ^ a[i]; ins(0); g[n + 1] = 0; for (int i = n; i >= 1; i--) { g[i] = max(g[i + 1], check(sum[i])); ins(sum[i]); } // get ans int ans = 0; for (int i = 1; i <= n - 1; i++) { ans = max(ans, f[i] + g[i + 1]); } cout << ans << "\n"; return 0; }
- 1
信息
- ID
- 693
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 5
- 标签
- 递交数
- 36
- 已通过
- 16
- 上传者