HDU - 5536 Chip Factory(带删除操作01字典树)

链接HDU - 5536 Chip Factory

题意:

给出 n ( 3 ≤ n ≤ 1000 ) n(3\le n\le1000) n(3n1000)个非负整数 s 1 , s 2 , ⋯   , s n s_1,s_2,\cdots,s_n s1,s2,,sn,求最大的 ( s i + s j ) ⊕ s k (s_i+s_j)\oplus s_k (si+sj)sk,其中 i , j , k i,j,k i,j,k互不相同且 1 ≤ i , j , k ≤ n 1\le i,j,k\le n 1i,j,kn



分析:

由于 n n n只有 1000 1000 1000,所以我们可以暴力枚举 i , j i,j i,j,然后在除 s i , s j s_i,s_j si,sj以外元素构成的01字典树中找到异或最大的 s k s_k sk

每次都去建树肯定不行,所以就要加一个数组 n u m [ u ] num[u] num[u]来实现带删除操作的01字典树,先把 s 1 s_1 s1~ s n s_n sn都放入01字典树,枚举了 i , j i,j i,j就删除 s i , s j s_i,s_j si,sj,询问最大异或值后再将 s i , s j s_i,s_j si,sj恢复即可。



以下代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=1000+50;
const int max_base=31;
int n;
int ch[31*maxn][2],num[31*maxn],tot;
LL s[maxn],val[31*maxn];
void init()
{
    tot=1;
    ch[0][0]=ch[0][1]=0;
    val[0]=0;
    num[0]=0;
}
void ins(LL x)
{
    int u=0;
    num[u]++;
    for(LL i=max_base;i>=0;i--)
    {
        LL c=(x>>i)&1LL;
        if(!ch[u][c])
        {
            ch[tot][0]=ch[tot][1]=0;
            val[tot]=0;
            num[tot]=0;
            ch[u][c]=tot++;
        }
        u=ch[u][c];
        num[u]++;
    }
    val[u]=x;
}
void updata(LL x,int op)   //op=-1:删除x
{                          //op=1:恢复之前被删除的x
    int u=0;
    num[u]+=op;
    for(LL i=max_base;i>=0;i--)
    {
        LL c=(x>>i)&1LL;
        u=ch[u][c];
        num[u]+=op;
    }
}
LL query(LL x)
{
    int u=0;
    for(LL i=max_base;i>=0;i--)
    {
        LL c=(x>>i)&1LL;
        if(ch[u][c^1]&&num[ch[u][c^1]])
            u=ch[u][c^1];
        else
            u=ch[u][c];
    }
    return x^val[u];
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        init();
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&s[i]);
            ins(s[i]);
        }
        LL ans=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                LL x=s[i]+s[j];
                updata(s[i],-1);
                updata(s[j],-1);
                ans=max(ans,query(x));
                updata(s[i],1);
                updata(s[j],1);
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值