[HDU 5536] Chip Factory (trie树+异或)

链接

HDU 5536


题意

给出n个数(n >= 3),求n个数中任意三个不同的数a、b、c的(a + b) ^ c的最大值。


题解

一种trie树的经典用法,和异或操作结合求最值的问题。
将输入的数二进制化后,全部存在trie树中(注意补齐到31位),然后枚举a和b,在trie树中寻找相应的c即可。
由于要满足a、b、c不同,在选定a、b后需要将他们的二进制串从trie树中消除,得出结果后再添加进去,这里用一个路径去计数就可以了,详情看代码。


代码
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn (1010)
int trie_nd[1010];
struct Trie
{
    #define maxk (40000)
    #define degree (2)
    #define next nnext
    #define prev pprev
    int next[maxk][degree], prev[maxk], nd[maxk], inc_nod[maxk];
    int L, root;
    int newnode()
    {
        next[L][0] = next[L][1] = -1;
        nd[L] = inc_nod[L] = prev[L] = 0;
        return L++;
    }
    int init() { L = 0; root = newnode(); }
    void insert(int val[], int n, int id)
    {
        int now = root;
        for(int i = 0, key; i < n; i++)
        {
            key = val[i];
            if(next[now][key] == -1)
                next[now][key] = newnode();
            prev[next[now][key]] = now;
            now = next[now][key];
            inc_nod[now]++;
        }
        nd[now] = 1;
        trie_nd[id] = now;
    }
    void recall(int nodid, int val)
    {
        if(nodid == root) return;
        inc_nod[nodid] += val;
        recall(prev[nodid], val);
    }
    int solve(int val[], int n)
    {
        int now = root, ret = 0;
        for(int i = 0, need; i < n; i++)
        {
            need = val[i] ? 0 : 1;
            if(next[now][need] == -1 || !inc_nod[next[now][need]])
            {
                ret <<= 1;
                ret |= 0;
                now = next[now][need^1];
            }
            else
            {
                ret <<= 1;
                ret |= 1;
                now = next[now][need];
            }
        }
        return ret;
    }
} trie;

int buf[50], buf0[50];
int* to01(int x)
{
    int k = 0;
    while(x) { buf0[k++] = x & 1; x >>= 1; }
    int i;
    for(i = 0; i < 31 - k; i++) buf[i] = 0;
    while(k) { buf[i++] = buf0[k-1]; k--; }
    return buf;
}
int str01[maxn][32], a[maxn];
int main()
{
    int T;
    cin >> T;
    while(T--)
    {
        trie.init();
        int n;
        cin >> n;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
            trie.insert(to01(a[i]), 31, i);
        }
        int ans = 0;
        for(int i = 1; i < n; i++)
        {
            for(int j = i + 1; j <= n; j++)
            {
                trie.recall(trie_nd[i], -1);
                trie.recall(trie_nd[j], -1);
                ans = max(ans, trie.solve(to01(a[i] + a[j]), 31));
                trie.recall(trie_nd[i], 1);
                trie.recall(trie_nd[j], 1);
            }
        }
        cout << ans << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值