Xor Sum
Time Limit: 1000 MS
Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大。Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助。你能证明人类的智慧么?
Input
输入包含若干组测试数据,每组测试数据包含若干行。
输入的第一行是一个整数T(T < 10),表示共有T组数据。
每组数据的第一行输入两个正整数N,M(<1=N,M<=100000),接下来一行,包含N个正整数,代表 Zeus 的获得的集合,之后M行,每行一个正整数S,代表 Prometheus 询问的正整数。所有正整数均不超过2^32。
Output
对于每组数据,首先需要输出单独一行”Case #?:”,其中问号处应填入当前的数据组数,组数从1开始计算。
对于每个询问,输出一个正整数K,使得K与S异或值最大。
Sample Input
2
3 2
3 4 5
1
5
4 1
4 6 5 6
3
Sample Output
Case #1:
4
3
Case #2:
4
给出n个数,m次查询,每次查询输出异或值最大的那个数。
01字典树,原来字典树还有这种操作。
从高位向低位创建一棵字典树,val记录字典树的节点所代表的数值,查询的时候从高位开始向低位查询,每次贪心找到异或值最大的,输出该节点所代表的数值。
#include "bits/stdc++.h" using namespace std; typedef long long LL; const int maxn = 100000 + 10; int ch[32*maxn][2]; LL val[32*maxn]; int sz; void init(){ memset(ch[0], 0 ,sizeof(ch[0])); sz = 1; } void insert_01tree(LL a){ int u = 0; for(int i = 31; i >= 0; i--) { int c = ((a>>i)&1); if(!ch[u][c]){ //新开节点,使得上一级的节点指向新开的节点 memset(ch[sz], 0, sizeof(ch[sz])); val[sz]=0; ch[u][c] = sz++; } u = ch[u][c]; } val[u] = a; //储存当前的值 } LL query(LL a){ int u = 0; for(int i = 31; i >= 0; i--){ int c = ((a>>i)&1); if(ch[u][c^1]) u = ch[u][c^1]; else u = ch[u][c]; } return val[u]; } int main(int argc, char const *argv[]) { int T; int Kcase = 0; scanf("%d", &T); while (T--) { LL a; init(); int N, M; scanf("%d%d", &N, &M); for (int i = 0; i < N; i++) { scanf("%lld", &a);insert_01tree(a); } printf("Case #%d:\n", ++Kcase); while (M--) { scanf("%lld", &a); printf("%lld\n", query(a)); } } return 0; }
Chip Factory
题意:
给一个数组A,从A中找到两个数使得两个数的和和数组中的另外一个的异或最大
枚举每两个数,将它们从字典树上删去,再查找和他们异或和最大的,然后在把两个数加到字典树上。用一个数组num记录每个数在字典树上的贡献,删去一个数只要把它的贡献减去就可以了。
#include "bits/stdc++.h" using namespace std; typedef long long LL; const int maxn = 1e5; LL a[maxn], val[maxn]; int ch[maxn][2], num[maxn]; int sz = 1; void insert_01tree(LL x) { int u = 0; for (int i = 32; i >= 0; i--) { int c = ((x>>i)&1); if (!ch[u][c]) { memset(ch[sz], 0, sizeof(ch[sz])); num[sz] = 0; val[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; num[u]++; } val[u] = x; } void updata(LL x, int d) { int u = 0; for (int i = 32; i >= 0; i--) { int c = ((x>>i)&1); u = ch[u][c]; num[u] += d; } } LL query(LL x) { int u = 0; for (int i = 32; i >= 0; i--) { int c = ((x>>i)&1); if(num[ch[u][c^1]] and ch[u][c^1]) u = ch[u][c^1]; else u = ch[u][c]; } return val[u]; } void init() { memset(ch[0], 0, sizeof(ch[0])); memset(val, 0, sizeof(val)); memset(num, 0, sizeof(num)); sz = 1; } int main(int argc, char const *argv[]) { int T; scanf("%d", &T); while (T--) { init(); int N; LL maxx = 0; scanf("%d", &N); for (int i = 0; i < N; i++) scanf("%lld", a+i), insert_01tree(a[i]); for (int i = 0; i < N; i++) { for (int j = i + 1; j < N; j++) { updata(a[i], -1); updata(a[j], -1); maxx = max(maxx ,(a[i]+a[j]) xor query(a[i]+a[j])); updata(a[i], 1); updata(a[j], 1); } } printf("%lld\n", maxx); } return 0; }