hdu 5536 Chip Factory 01trie+可删除

来源:互联网 发布:软件管家360官方下载 编辑:程序博客网 时间:2024/06/05 20:33


题目链接


题意:

求max( (a[i] + a[j]) a[k] ) (i, j, k都不相同)

思路:

这题可以暴力也可以01trie. 来说说01trie.
其实遇到异或求最大最小啊啥的都可以想01trie是否可做.
那么这个题肯定就是枚举两个和,然后跑01trie了.

关键是怎么解决下标不同的问题,这里解决办法是增加一个del函数,删除以某个前缀为数的个数.
即:num[]保存的是到该节点,以该前缀 的数的个数有多少,我们-1就相当于把这个数删除了.
具体见代码

#include<bits/stdc++.h>using namespace std;typedef long long ll;const int mod=1e9+7;const int maxn=1e5+10;typedef long long ll;int a[maxn];int n;int trie[maxn][3];int num[maxn];int now;void init(){    now = 1;    memset(trie[0],0,sizeof trie[0]);    return ;}void insert(int x)//插入 {    int d = 0;    for(int i = 31;i >= 0;--i)    {        int tmp = (x >> i) & 1;//傻逼错误啊 = =         if(!trie[d][tmp])        {            num[now] = 0;            memset(trie[now],0,sizeof trie[now]);            trie[d][tmp] = now++;        }        d = trie[d][tmp];        num[d]++;    }    return ;}void del(int x)//删除操作 {    int d = 0;    for(int i = 31;i >= 0;--i)    {        int tmp = (x >> i) & 1;        d = trie[d][tmp];        num[d]--;//前缀个数-1即可     }    return ;}int find(int x)//匹配 {    int res = 0,d = 0;    for(int i = 31;i >= 0;--i)    {        int tmp = (x >> i) & 1;        if(trie[d][tmp^1] && num[trie[d][tmp^1]])        {            res |= (1 << i);            d = trie[d][tmp^1];        }        else        d = trie[d][tmp];    }    return res;}int main(){    int _;    cin>>_;    while(_--)    {        scanf("%d",&n);        init();        for(int i = 1;i <= n;++i)        {            scanf("%d",&a[i]);              insert(a[i]);        }           int ans = 0;        for(int i = 1;i <= n;++i)        {            del(a[i]);            for(int j = i + 1;j <= n;++j)            {                del(a[j]);                int s= a[i]+a[j];                ans = max(ans,find(s));                insert(a[j]);            }            insert(a[i]);        }        printf("%d\n",ans);    }    return 0;}
原创粉丝点击