HDU 4825 Xor Sum(前缀树)

版权声明:没人会转的( ̄▽ ̄") https://blog.csdn.net/j2_o2/article/details/83056046
题意

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;
}

猜你喜欢

转载自blog.csdn.net/j2_o2/article/details/83056046
今日推荐