题意
Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大。Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助。你能证明人类的智慧么?
思路
运用前缀树贪心,每次能走相反结点,就走相反结点,顺便记录走过的结点权值和即可。
代码
#include <stdio.h>
#include <algorithm>
using namespace std;
#define rd(a) (a = read())
#define mem(a,b) memset(a,b,sizeof(a))
#define Wh(a) while(a)
#define ll long long
#define INF 0x3f3f3f3f
#define eps 1e-6
#define pi acos(-1.0)
inline ll read()
{
char ch = getchar();
ll x = 0, f = 1;
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while('0' <= ch && ch <= '9') x = x*10 + ch - '0', ch = getchar();
return x*f;
}
ll cnt;
struct tree
{
ll nxt[2];
void init()
{
nxt[0] = nxt[1] = 0;
}
}T[3200005];
void ins(ll a)
{
ll now = 0;
for(ll i = 31; ~i; --i)
{
ll flag = (a>>i)&1;
if(!T[now].nxt[flag])
{
T[cnt].init();
T[now].nxt[flag] = cnt++;
}
now = T[now].nxt[flag];
}
}
ll query(ll a)
{
ll now = 0, ans = 0;
for(ll i = 31; ~i; --i)
{
ll flag = (a>>i)&1;
if(T[now].nxt[flag^1])
{
if(flag == 0) ans += (1ll<<i);
now = T[now].nxt[flag^1];
}
else
{
if(flag == 1) ans += (1ll<<i);
now = T[now].nxt[flag];
}
}
return ans;
}
int main()
{
for(ll t = read(), i = 1; t; --t, ++i)
{
cnt = 1, T[0].init();
printf("Case #%lld:\n",i);
ll n = read(), m = read();
while(n--) ins(read());
while(m--) printf("%lld\n",query(read()));
}
return 0;
}