首页 > 代码库 > Codechef Xor it (March 12 challenge)

Codechef Xor it (March 12 challenge)

题意很简单,给定N <= 10^5个数,问你两两异或的前k小值。1 ≤ K ≤ min{250000, N*(N-1)/2},a[i] < 2^31

容易想到,要建一个0/1串的trie树,然后考虑每层实际上就是二进制的每一位,然后我们看看ΣC(size,2)是否达到了k,因为这位有ΣC(size,2)对数异或值为0。我们要找的是第一个满足条件的位数,统计前k小即可。实际实现的时候我们可以考虑,把一个数组排个序,其实每段区间就是trie树中的每一层,不需要把trie建出来。二分位数,对每一位计算区间即可。

代码参考了钦爷的代码,感觉吊炸天

Code

#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
int n, k, a[N];
vector<int> ans;
int main() {
	scanf("%d%d", &n, &k);
	for (int i = 0; i < n; ++i)	scanf("%d", &a[i]);
	sort(a, a + n);
	int l = -1, r = 31;
	while (l < r - 1) {
		int mid = l + r >> 1;
		long long sum = 0ll;
		int i, j;
		for (i = j = 1; i < n; ++i) {
			if ((a[i] ^ a[i - 1]) < 1 << mid)	++j;//实际是trie
			else sum += (long long)j * (j - 1) / 2, j = 1;
		}
		sum += (long long)j * (j - 1) / 2;
		if (sum >= k)	r = mid;
		else l = mid;
	}
	if (r == 0)	for (int i = 0; i < k; ++i)	printf("0 ");
	else {
		int i, j;
		for (i = 1, j = 0; i < n; ++i) {
			if ((a[i] ^ a[i - 1]) < 1 << r) 
				for (int l = j; l < i; ++l)	ans.push_back(a[i] ^ a[l]);
			else j = i;
		}
		partial_sort(ans.begin(), ans.begin() + k, ans.end());
		for (i = 0; i < k; ++i)	printf("%d ", ans[i]);
	}
	puts("");
	return 0;
}


Codechef Xor it (March 12 challenge)