usaco6.1.3 Cow XOR

3 篇文章 0 订阅

一 原题

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)

5
1
0
5
4
2

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:maxkibb3
LANG: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;
			else
				root = Trie[root].right;
		}
		else {
			if(Trie[root].right != -1)
				root = Trie[root].right;
			else
				root = 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: cowxor
LANG: C++

Compiling...
Compile: OK

Executing...
   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:maxkibb3
LANG: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;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值