Chip Factory(HDU 5536)

Chip Factory

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


题目要求在一个数组里找出下标不同的i,j,k,求a[i]+a[j]异或a[k]的最大值;

第一种解法,显然O(n^3)暴力;
但是这个暴力也有讲究,不能随便乱暴;

第二种解法,01字典树;
跟模板题最大的区别就是,我要从中拿两个下标不同的数来相加,和数组里另外一个数求异或值,显然拿出来的两个数就必须从树中消失,怎么消失呢?我们可以记录每个结点的经过值,消失就减一,添加就加一;

对于字典树来说,memset清0最好不要用,尤其是有多种测试数据时,非常耗时间;

代码:

#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define lson k<<1
#define rson k<<1|1
//ios::sync_with_stdio(false);
using namespace std;
const int N=50010;
const int M=200100;
const LL mod=1e9+7; 
int tr[N][32],val[N],s[N],a[N];
int rt;
void init(){
	rt=0;
	tr[0][1]=0;
	tr[0][0]=0;
//	memset(tr,0,sizeof(tr));//尽量不要用 
//	memset(val,0,sizeof(val));
//	memset(s,0,sizeof(s));
}
void add(int p){
	int k=0;
	for(int i=31;i>=0;i--){
		int d=(p>>i)&1;
		if(!tr[k][d]){
			tr[k][d]=++rt;
			tr[rt][0]=tr[rt][1]=0;
			val[rt]=0;
			s[rt]=0;
		}
		k=tr[k][d];
		s[k]++;
	}
	val[k]=p;
} 
void update(int p,int q){//从树中删除或者添加某个数
	int k=0;
	for(int i=31;i>=0;i--){
		int d=(p>>i)&1;
		if(!tr[k][d]) break;
		k=tr[k][d];
		s[k]+=q;
	}
}
int search(int p){
	int k=0;
	for(int i=31;i>=0;i--){
		int d=(p>>i)&1;
		if(tr[k][d^1]&&s[tr[k][d^1]]) k=tr[k][d^1];
		else k=tr[k][d];
	}
	return val[k]^p;
} 
int main(){
	ios::sync_with_stdio(false);
	int t;
	cin>>t;
	while(t--){
		init();
		int n;
		cin>>n;
		for(int i=1;i<=n;i++){
			cin>>a[i];
			add(a[i]);
		}
		int mmax=0;
		for(int i=1;i<=n;i++){
			for(int j=i+1;j<=n;j++){
				update(a[i],-1);
				update(a[j],-1);//删除
				mmax=max(mmax,search(a[i]+a[j]));
				update(a[i],1);
				update(a[j],1);//添加 
			}
		}
		cout<<mmax<<endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值