HDU - 5536 Chip Factory 字典树的删除

Chip Factory

Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 6090    Accepted Submission(s): 2745


 

Problem Description

John is a manager of a CPU chip factory, the factory produces lots of chips everyday. To manage large amounts of products, every processor has a serial number. More specifically, the factory produces n chips today, the i-th chip produced this day has a serial number si.

At the end of the day, he packages all the chips produced this day, and send it to wholesalers. More specially, he writes a checksum number on the package, this checksum is defined as below:

maxi,j,k(si+sj)⊕sk


which i,j,k are three different integers between 1 and n. And ⊕ is symbol of bitwise XOR.

Can you help John calculate the checksum number of today?

 

 

Input

The first line of input contains an integer T indicating the total number of test cases.

The first line of each test case is an integer n, indicating the number of chips produced today. The next line has n integers s1,s2,..,sn, separated with single space, indicating serial number of each chip.

1≤T≤1000
3≤n≤1000
0≤si≤109
There are at most 10 testcases with n>100

 

 

Output

For each test case, please output an integer indicating the checksum number in a line.

 

 

Sample Input

 

2 3 1 2 3 3 100 200 300

 

 

Sample Output

 

6 400

 

 

Source

2015ACM/ICPC亚洲区长春站-重现赛(感谢东北师大)

 

 

Recommend

hujie

题意:n个数,求任取两个数的加和,与剩下的数异或的最大值

分析:

01字典树求异或的最大值,需要删除操作,因为01字典树,我们可以对每一个节点进行标记,num[u]表示插入字符的01串经过该节点的次数,删除的时候,遍历数字二进制所对应的节点01,使其num【u】-1就可以了。(其实num跟统计前缀差不多作用)

 

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1005;
const int maxnode=1000000+100;
int num[maxnode];
const int sigma_size=3;
struct Trie
{
    int ch[maxnode][sigma_size];
    int sz;
    void init()
    {
        sz=1;
        memset(ch[0],0,sizeof(ch[0]));
    }
    void insert(ll x)
    {
        int u=0;
        for(int i=32;i>=0;i--)
        {
            int id=(x>>i)&1;//取出x二进制第i位
            if(ch[u][id]==0)
            {
                ch[u][id]=sz;
                
                memset(ch[sz],0,sizeof(ch[sz]));
                num[sz]=0;
                sz++;
            }
            u=ch[u][id];
            num[u]++;
		
        }
        
    }
    void update(ll x, int d)
	{
     int u = 0;
     for(int i =32; i >= 0; i--){
        int index = (x>>i)&1;
        u = ch[u][index];
        num[u]+=d;
    }
    }
    ll find(ll x)
    {
    	ll ans=0;
    	int u=0;
        for(int i=32;i>=0;i--)
        {
            int id=(x>>i)&1;
            int y=id^1;    //找与id不同的
            if(ch[u][y]&&num[ch[u][y]])
            {
			 u=ch[u][y];
			 ans=ans<<1|1;  //不同为1,ans=ans*2+1
            }
            else
			{
			u=ch[u][id];
			 ans<<=1;      //相同为0,ans=ans*2
			 	
			}
        }
        return ans;
    }
};
Trie trie;
ll a[N];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
   {
    ll  maxx=0;
    int n;
	trie.init();
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]); 
		trie.insert(a[i]);
	}
	for(int i=1;i<n;i++)
	   for(int j=i+1;j<=n;j++)
	  {
	  	trie.update(a[i],-1);
	  	trie.update(a[j],-1);
		maxx=max(maxx,trie.find(a[i]+a[j]));
		trie.update(a[i],1);
	  	trie.update(a[j],1);
	  }	
	
	cout<<maxx<<endl;
   }
	
    return 0;
}

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值