HDU.5536.Chip Factory(01字典树)

HDU.5536.Chip Factory(01字典树)

思路: 01 01 字典树 + + 暴力。

考虑:求枚举 i , j i,j ,因为 i , j i,j 等价所以我们可以假设 1 i < j n 1\le i<j\le n

然后对于 k k ,我们用一个 01 01 字典树维护查询。

需要注意的是:先删除 a [ i ] , a [ j ] a[i],a[j] ,再查询,然后再将 a [ i ] , a [ j ] a[i],a[j] 插入还原,继续下一个查询。

对于删除我们动态维护一个 s z [ ] sz[] 数组记录该结点出现的次数,对于查询我们用一个 v a l [ ] val[] 数组维护从该根到该节点的路径的异或和 v a l val

时间复杂度: O ( n 2 l o g n ) O(n^2logn)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+5,M=3e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
struct Trie{
	int son[M][2],sz[M],cnt,val[M];
	void init(){cnt=0,mst(son[0]);} 
	void ins(int x){	//插入. 
	int p=0;
	for(int i=30;~i;i--){
		int &s=son[p][x>>i&1];
		if(!s) s=++cnt,mst(son[cnt]),sz[cnt]=val[cnt]=0;
		p=s,sz[p]++;
	}
	val[p]=x;
	}
	void del(int x){	//删除. 
		int p=0;
		for(int i=30;~i;i--){
			int s=x>>i&1;
			p=son[p][s];
			--sz[p];
		}
	}
	int que(int x){		//查询. 
		int p=0;
	for(int i=30;~i;i--){
		int s=x>>i&1;
		if(son[p][!s]&&sz[son[p][!s]]) p=son[p][!s];
		else p=son[p][s];
	} 
	return x^val[p]; 
	}
}T;
int t,n,a[N],ans;
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);T.init();ans=0;//初始化 
		for(int i=1;i<=n;i++) scanf("%d",&a[i]),T.ins(a[i]);
		for(int i=1;i<n;i++){	//先删除,查询再插入. 
			T.del(a[i]);
			for(int j=i+1;j<=n;j++){
				T.del(a[j]);
				ans=max(ans,T.que(a[i]+a[j]));
				T.ins(a[j]);
			}
			T.ins(a[i]);
		}
		printf("%d\n",ans);
	}	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/107592263
今日推荐