标签:
题目大意
给出一个序列,求一个连续的子序列的异或和最大.
题解
先探究一下异或的性质.
1.可逆性: A XOR B XOR B = A;
2.满足结合律: (A XOR B) XOR C = A XOR (B XOR C);
利用以上两个性质有助于我们解题.
假设有一序列 A1,A2,A3......An-1,An ,可以得到另一序列 B1,B2,B3......Bn-1,Bn ,其中Bi表示A序列前i个元素的异或和.
所以,要求A序列从i到j的异或和就是Bj-Bi-1.
用这个结论就可以写一个时间复杂度为O(N2)的算法了.
再观察一下可发现这一个简单的结论,无论什么进制下,高位往往决定这个数的大小.所以我们需要一种数据结构能够支持我们快速查找最优的位置.
TRIE树?!可以,这很强势!
然后按二进制的位存储即可.O(N*20)23333333什么鬼.
严格来说TRIE树如果开数组的话要100w*2的,但奈何USACO的数据蒻,开了10w*2就AC了.
详情请看代码.
代码
/* TASK:cowxor LANG:C++ */ #include <cstdio> #include <cstring> using namespace std; const int MAXN = 100005; int a[MAXN], b[MAXN], ans, st, ed, n; int ch[MAXN * 10][2], node; void insert(int num) { int u = 0; for (int i = 20; i >= 0; --i) { int now = ((b[num] >> i) & 1); if (ch[u][now]) u = ch[u][now]; else { ch[u][now] = ++node; u = node; } } ch[u][0] = num; } int findmx(int num) { int u = 0; for (int i = 20; i >= 0; --i) { int now = ((b[num] >> i) & 1); if (ch[u][now ^ 1]) u = ch[u][now ^ 1]; else u = ch[u][now]; } return ch[u][0]; } int main() { freopen("cowxor.in", "r", stdin); freopen("cowxor.out", "w", stdout); scanf("%d", &n); scanf("%d", &a[0]); b[0] = a[0]; ans = b[0]; st = ed = 0; for (int i = 1; i < n; ++i) scanf("%d", &a[i]), b[i] = a[i] ^ b[i - 1]; memset(ch, 0, sizeof(ch)); node = 0; insert(0); for (int i = 1; i < n; ++i) { int j = findmx(i); if (ans < (b[i] ^ b[j])) { ans = b[i] ^ b[j]; st = j + 1; ed = i; } insert(i); } printf("%d %d %d\n", ans, st+1, ed+1); return 0; }
标签:
原文地址:http://www.cnblogs.com/albert7xie/p/5730565.html