标签:style http ar color sp for on art bs
题意很简单,给定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建出来。二分位数,对每一位计算区间即可。
代码参考了钦爷的代码,感觉吊炸天
#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)
标签:style http ar color sp for on art bs
原文地址:http://blog.csdn.net/mlzmlz95/article/details/41693039