LightOJ 1269 Consecutive Sum (Trie树)
Jan's LightOJ :: Problem 1269 - Consecutive Sum
题意是,求给定序列的中,子序列最大最小的抑或和。
做法就是用一棵Trie树,记录数的每一位是0还是1。查询的时候,如果求最大值,就尽量让高位是1,相反就尽量让高位是0。
代码如下,1y:
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 6 using namespace std; 7 8 const int N = 55555; 9 const int M = 32; 10 11 struct Node { 12 int c[2]; 13 void init() { c[0] = c[1] = -1;} 14 } ; 15 16 struct Trie { 17 Node node[M * N]; 18 int rt, curid; 19 void init() { rt = curid = 0; node[curid++].init();} 20 void insert(int x, int dg = 32) { 21 int p = rt; 22 for (int i = dg - 1, idx; i >= 0; i--) { 23 idx = (x & 1 << i) != 0; 24 if (node[p].c[idx] == -1) node[node[p].c[idx] = curid++].init(); 25 p = node[p].c[idx]; 26 } 27 } 28 int min(int x, int dg = 32) { 29 int p = rt, ret = 0; 30 for (int i = dg - 1, idx; i >= 0; i--) { 31 idx = (x & 1 << i) != 0; 32 if (~node[p].c[idx]) p = node[p].c[idx], ret <<= 1, ret |= idx; 33 else p = node[p].c[!idx], ret <<= 1, ret |= !idx; 34 } 35 return ret; 36 } 37 int max(int x, int dg = 32) { 38 int p = rt, ret = 0; 39 for (int i = dg - 1, idx; i >= 0; i--) { 40 idx = (x & 1 << i) == 0; 41 if (~node[p].c[idx]) p = node[p].c[idx], ret <<= 1, ret |= idx; 42 else p = node[p].c[!idx], ret <<= 1, ret |= !idx; 43 } 44 return ret; 45 } 46 } trie; 47 48 int main() { 49 int T, n, x; 50 scanf("%d", &T); 51 for (int cas = 1; cas <= T; cas++) { 52 scanf("%d", &n); 53 int ans1 = 0x80000000, ans2 = 0x7fffffff, sum = 0; 54 trie.init(); 55 trie.insert(0); 56 for (int i = 0; i < n; i++) { 57 scanf("%d", &x); 58 sum ^= x; 59 //cout << sum << endl; 60 ans1 = max(ans1, trie.max(sum) ^ sum); 61 ans2 = min(ans2, trie.min(sum) ^ sum); 62 trie.insert(sum); 63 } 64 printf("Case %d: %d %d\n", cas, ans1, ans2); 65 } 66 return 0; 67 }
其实做这题的时候想到一种比较麻烦的情况,那就是数里面有负数。这样的话需要对最高位特判,从而求得最大最小值。不过没有这样的数据,所以就不这么搞了。
——written by Lyon