牛客提高D1t2 最小生成链
分析
我们发现可以把题目转化为:有一个序列a,问它的排列中相邻两个值异或的最大值的最小值
我们发现序列的构成一定是前几位全是一样的
从某一位开始左面全是0右面全是1
所以只要找到一种方案是的交界两个值异或最小即可
把是0的插入01trie,每次拿是1的查询异或最小值
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
int n,m,sum[60000100][2],trie[60000100][2],cnt;
long long a[1000100],res,ans;
inline void q(long long x){
int i,p=0;
for(i=59;i>=0;i--){
int wh=(x&(1ll<<i))?1:0;
if(trie[p][wh]){
p=trie[p][wh];
}else p=trie[p][wh^1],res|=(1ll<<i);
}
return;
}
inline void ins(long long x){
int i,p=0;
for(i=59;i>=0;i--){
int wh=(x&(1ll<<i))?1:0;
if(!trie[p][wh])
trie[p][wh]=++cnt;
p=trie[p][wh];
}
return;
}
signed main(){
int i,j,k,pl=-1;
scanf("%d",&n);
ans=(1ll<<60);
for(i=1;i<=n;i++){
scanf("%lld",&a[i]);
for(j=0;j<60;j++){
int wh=((1ll<<j)&a[i])?1:0;
sum[j][wh]++;
}
}
for(i=59;i>=0;i--){
if(sum[i][0]==n||sum[i][1]==n)continue;
pl=i;
break;
}
for(i=1;i<=n;i++)
if(!((1ll<<pl)&a[i])){
ins(a[i]);
}
for(i=1;i<=n;i++)
if((1ll<<pl)&a[i]){
res=0;
q(a[i]);
//cout<<i<<' '<<res<<endl;
ans=min(ans,res);
}
if(pl==-1)puts("0");
else printf("%lld\n",ans);
return 0;
}