usaco6.1.3 Cow XOR

来源:互联网 发布:java 设置useragent 编辑:程序博客网 时间:2024/05/16 14:39

一 原题

Cow XOR
Adrian Vladu -- 2005

Farmer John is stuck with another problem while feeding his cows. All of his N (1 ≤ N ≤ 100,000) cows (numbered 1..N) are lined up in front of the barn, sorted by their rank in their social hierarchy. Cow #1 has the highest rank; cow #N has the least rank. Every cow had additionally been assigned a non-unique integer number in the range 0..(221 - 1).

Help FJ choose which cows will be fed first by selecting a sequence of consecutive cows in the line such that the bitwise "xor" between their assigned numbers has the maximum value. If there are several such sequences, choose the sequence for which its last cow has the highest rank. If there still is a tie, choose the shortest sequence.

TIME LIMIT: 0.5 sec

PROGRAM NAME: cowxor

INPUT FORMAT

  • Line 1: A single integer N
  • Lines 2..N+1: N integers ranging from 0 to 221 - 1, representing the cows' assigned numbers. Line j describes cow of social hierarchy j-1.

SAMPLE INPUT (file cowxor.in)

510542

INPUT DETAILS:

There are 5 cows. Cow #1 had been assigned with 1; cow #2 with 0; cow #3 with 5; cow #4 with 4; cow #5 with 2.

OUTPUT FORMAT

  • Line 1: Three space-separated integers, respectively: the maximum requested value, the position where the sequence begins, the position where the sequence ends.

SAMPLE OUTPUT (file cowxor.out)

6 4 5

OUTPUT DETAILS:

4 xor 2 = 6 (001) xor (010) = (011) 


二 分析

求出前n个数的异或结果Xor[n],那么问题转化为在n个数中找到异或结果最大的两个。因为N可能会到10w,所以O(n^2)的方法是过不了的。我们考虑建立一棵字母表为0,1的Trie树,这样给定一个数,寻找与它异或结果最大的数的时间复杂度会降到lg(Xor[i])级别(输入数字的大小不超过2^21,异或结果也不会超过2^21)。这题坑爹的地方在于usaco卡内存。。


三 代码

先附上我蠢蠢的会爆内存的trie树代码:
/*ID:maxkibb3LANG:C++PROB:cowxor*/#include<cstdio>#include<bitset>const int MAX = 1e5 + 5;int N, Arr[MAX], Xor[MAX], Trie_size;struct Node {int val, left, right;Node() { val = 0; left = right = -1; }Node(int _v) : val(_v) { left = right = -1; }}Trie[MAX * 5];void create(int _v, int _f) {if(_v) Trie[_f].right = Trie_size;else Trie[_f].left = Trie_size;Trie[Trie_size++] = Node(_v);}void insert(int _v, int _i) {std::bitset<21> bits(_v);int root = 0;for(int i = 20; i >= 0; i--) {if(bits[i]) {if(Trie[root].right == -1)create(1, root);root = Trie[root].right;}else {if(Trie[root].left == -1)create(0, root);root = Trie[root].left;}}create(_i, root);}int find(int _v) {std::bitset<21> bits(_v);int root = 0;for(int i = 20; i >= 0; i--) {if(bits[i]) {if(Trie[root].left != -1)root = Trie[root].left;elseroot = Trie[root].right;}else {if(Trie[root].right != -1)root = Trie[root].right;elseroot = Trie[root].left;}}return Trie[Trie[root].right].val;}int main() {freopen("cowxor.in", "r", stdin);freopen("cowxor.out", "w", stdout);scanf("%d", &N);Trie[Trie_size++] = Node(0);for(int i = 1; i <= N; i++)scanf("%d", &Arr[i]);int ans = Arr[1], l = 1, r = 1;for(int i = 1; i <= N; i++) {Xor[i] = Xor[i - 1] ^ Arr[i];insert(Xor[i], i);int idx = find(Xor[i]);int tmp = Xor[idx] ^ Xor[i];if(tmp > ans) ans = tmp, l = idx + 1, r = i;}printf("%d %d %d\n", ans, l, r);return 0;}



运行结果:
USER: Qi Shen [maxkibb3]TASK: cowxorLANG: C++Compiling...Compile: OKExecuting...   Test 1: TEST OK [0.000 secs, 8664 KB]   Test 2: TEST OK [0.000 secs, 8664 KB]   Test 3: TEST OK [0.000 secs, 8664 KB]   Test 4: TEST OK [0.000 secs, 8664 KB]   Test 5: TEST OK [0.028 secs, 8928 KB]   Test 6: TEST OK [0.084 secs, 9984 KB]   Test 7: TEST OK [0.112 secs, 9324 KB]   Test 8: TEST OK [0.140 secs, 11172 KB]   Test 9: TEST OK [0.084 secs, 8664 KB]   Test 10: TEST OK [0.056 secs, 8664 KB]   Test 11: TEST OK [0.056 secs, 8664 KB]   Test 12: TEST OK [0.126 secs, 10116 KB]   Test 13: TEST OK [0.042 secs, 8664 KB]   Test 14: TEST OK [0.098 secs, 8664 KB]   Test 15: TEST OK [0.308 secs, 11700 KB]   Test 16: TEST OK [0.294 secs, 11700 KB]   Test 17: TEST OK [0.294 secs, 11700 KB]   Test 18: TEST OK [0.210 secs, 10908 KB]   Test 19: TEST OK [0.028 secs, 8928 KB]   Test 20: TEST OK [0.000 secs, 8664 KB]All tests OK.



AC代码:
/*ID:maxkibb3LANG:C++PROB:cowxor*/#include<cstdio>#include<bitset>#include<cstring>#include<map>#define left(x) ((x << 1) + 1)#define right(x) ((x << 1) + 2)const int MAX = 1e5 + 5;int N, Xor[MAX];bool Trie[1 << 22];std::map<int, int> M;void insert(int _v, int _i) {std::bitset<21> bits(_v);int root = 0;for(int i = 20; i >= 0; i--) {if(bits[i]) root = right(root);else root = left(root);if(!Trie[root]) Trie[root] = 1;}std::map<int, int>::iterator it = M.find(root);if(it == M.end()) M.insert(std::make_pair(root, _i));else it->second = _i;}int find(int _v) {std::bitset<21> bits(_v);int root = 0, next;for(int i = 20; i >= 0; i--) {if(bits[i]) {next = left(root);if(Trie[next]) root = next;else root = right(root);}else {next = right(root);if(Trie[next]) root = next;else root = left(root);}}std::map<int, int>::iterator it = M.find(root);if(it != M.end()) return it->second;}int main() {freopen("cowxor.in", "r", stdin);freopen("cowxor.out", "w", stdout);scanf("%d", &N);for(int i = 1; i <= N; i++) {int tmp;scanf("%d", &tmp);Xor[i] = Xor[i - 1] ^ tmp;}int ans = Xor[1], l = 1, r = 1;for(int i = 1; i <= N; i++) {insert(Xor[i], i);int idx = find(Xor[i]);int tmp = Xor[idx] ^ Xor[i];if(tmp > ans) ans = tmp, l = idx + 1, r = i;}printf("%d %d %d\n", ans, l, r);return 0;}




原创粉丝点击