HDU 5536 Chip Factory

题目链接

给N个数,找出(a[i]+a[j])^a[k]的最大值,其中i,j,k,为不同的数。

用01字典树求解。

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e3+3;
int arr[maxn],cnt;

struct Node
{
    int a[2],sum;//a数组当前值存的是0还是1,sum当前节点下挂着几个子节点。
}tri[maxn*100];

void Insert(int x)
{
    int u=0;
    for(int i=31;i>=0;--i)//将要插入数转化为二进制,插入字典树
    {
        int t=(x>>i)&1;
        if(!tri[u].a[t])
            tri[u].a[t]=++cnt;//如果当前节点不存在,加上;cnt:当前节点数
        u=tri[u].a[t];
        ++tri[u].sum;
    }
}

void Delete(int x)//在字典树中删除某一个01串
{
    int u=0;
    for(int i=31;i>=0;--i)
    {
        int t=(x>>i)&1;
        u=tri[u].a[t];
        --tri[u].sum;
    }
}

int query(int x)//查询异或和的最大
{
    int u=0,ans=0;
    for(int i=31;i>=0;--i)
    {
        int t=(x>>i)&1,rev=tri[u].a[!t],cur=tri[u].a[t];//从高位开始,找字典树中是否存在与当前数相反的二进制位数
        if(rev&&tri[rev].sum>0)
            u=rev,ans|=(1<<i);
        else
            u=cur;//否则,往下顺着找相反二进制位数
    }
    return ans;
}

int main()
{
    int T,n;
    scanf("%d",&T);
    while(T--)
    {
        cnt=0;
        memset(tri,0,sizeof(tri));
        scanf("%d",&n);
        for(int i=0;i<n;++i)
            scanf("%d",&arr[i]),Insert(arr[i]);
        int ans=0;
        for(int i=0;i<n;++i)
        {
            Delete(arr[i]);//为了保证i,j,k各不相同
            for(int j=i+1;j<n;++j)
            {
                Delete(arr[j]);
                ans=max(ans,query(arr[i]+arr[j]));
                Insert(arr[j]);
            }
            Insert(arr[i]);
        }
        printf("%d\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jinghui_7/article/details/82903593
今日推荐