题目
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5536
题目来源:2015长春区域赛。
简要题意:求 maxi,j,k{(si+sj)⊕sk} , i,j,k 互异。
数据范围: 1⩽T⩽1000;3⩽n⩽1000;0⩽si⩽109
题解
现场听说三方大暴力能过,hdoj机子弱或者改了数据所以要用数据结构。
题意很简单易懂,主要是异或搞的时候可以用Trie来贪心搞,降低复杂度。
假如Trie是从前往后建的,则高位为 1 是最好的,于是只要走
32 层就能得到答案。具体来说就是对 sk 去建Trie,然后枚举 i,j 的组合,查询的时候去除 si,sj 查询完后再加上。
实现
如果考虑建 si+sj 的Trie,空间复杂度会过高。
实现可以用递归或者非递归的,后者会更快一点。
这是第一次写Trie,成功1A,但是看了学长代码觉得有点挫了,然后改了下。
原来的版本通用性有点差,然后性能也不够好,在此给出两个版本。
递归版本代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
// head
const int ST = 31;
const int MX_NODE = 3.5e4;
struct Node {
int l, r, v;
void clr() {
l = r = v = 0;
}
};
struct Trie {
Trie() {cnt = 0;}
int cnt;
int build(int cur, int c, int pos) {
bool isr = (1<<pos)&c;
node[cur].v++;
if (pos == -1) return cur;
int nxt;
if (isr) {
if (!node[cur].r) node[cur].r = getNewNode();
nxt = node[cur].r;
} else {
if (!node[cur].l) node[cur].l = getNewNode();
nxt = node[cur].l;
}
build(nxt, c, pos-1);
}
void del(int cur, int c, int pos) {
bool isr = (1<<pos)&c;
node[cur].v--;
if (pos == -1) return;
int nxt = isr ? node[cur].r : node[cur].l;
del(nxt, c, pos-1);
}
int getMaxXor(int cur, int c, int pos) {
if (node[cur].v == 0) return -1;
if (pos == -1) return 0;
bool isl = (1<<pos)&c;
int res, ans;
if (isl) {
res = node[cur].l == 0 ? -1 : getMaxXor(node[cur].l, c, pos-1);
ans = (res == -1) ? getMaxXor(node[cur].r, c, pos-1) : res + (1<<pos);
} else {
res = node[cur].r == 0 ? -1 : getMaxXor(node[cur].r, c, pos-1);
ans = (res == -1) ? getMaxXor(node[cur].l, c, pos-1) : res + (1<<pos);
}
return ans;
}
int getNewNode() {
node[++cnt].clr();
return cnt;
}
void init() {
cnt = 0;
node[0].clr();
}
Node node[MX_NODE];
};
Trie trie;
int a[1005];
int main()
{
int t, n;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
trie.init();
for (int i = 0; i < n; i++) {
scanf("%d", a+i);
trie.build(0, a[i], ST);
}
int ans = 0;
for (int i = 0; i < n; i++) {
trie.del(0, a[i], ST);
for (int j = i+1; j < n; j++) {
trie.del(0, a[j], ST);
ans = max(ans, trie.getMaxXor(0, a[i]+a[j], ST));
trie.build(0, a[j], ST);
}
trie.build(0, a[i], ST);
}
printf("%d\n", ans);
}
return 0;
}
非递归版本代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
// head
const int ST = 31;
const int MX_NODE = 3.5e4;
const int CHARSET = 2;
struct Node {
int v;
int p[CHARSET];
void clr() {
v = 0;
for (int i = 0; i < CHARSET; i++) p[i] = 0;
}
inline int get(int x) {
return p[x];
}
inline void set(int x, int v) {
p[x] = v;
}
};
struct Trie {
Trie() {cnt = 0;}
int cnt;
int build(int c) {
int cur = 0, bit;
for (int i = ST; i > -1; i--) {
Node &x = node[cur];
bit = (c>>i)&1;
if (!x.get(bit)) x.set(bit, getNewNode());
cur = x.get(bit);
node[cur].v++;
}
}
void del(int c) {
int cur = 0, bit;
for (int i = ST; i > -1; i--) {
bit = (c>>i)&1;
cur = node[cur].get(bit);
node[cur].v--;
}
}
int getMaxXor(int c) {
int cur = 0, ans = -1, bit, nxt;
for (int i = ST; i > -1; i--) {
Node &x = node[cur];
bit = ((c>>i)&1)^1;
if (!node[x.get(bit)].v) bit ^= 1, ans ^= (1<<i);
cur = x.get(bit);
}
return ans;
}
int getNewNode() {
node[++cnt].clr();
return cnt;
}
void init() {
cnt = 0;
node[0].clr();
}
Node node[MX_NODE];
};
Trie trie;
int a[1005];
int main()
{
int t, n;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
trie.init();
for (int i = 0; i < n; i++) {
scanf("%d", a+i);
trie.build(a[i]);
}
int ans = 0;
for (int i = 0; i < n; i++) {
trie.del(a[i]);
for (int j = i+1; j < n; j++) {
trie.del(a[j]);
ans = max(ans, trie.getMaxXor(a[i]+a[j]));
trie.build(a[j]);
}
trie.build(a[i]);
}
printf("%d\n", ans);
}
return 0;
}