Description
You are given a complete undirected graph with n vertices. A number a i a_{i} ai is assigned to each vertex, and the weight of an edge between vertices i and j is equal to a i ⨁ a j a_{i}\bigoplus a_{j} ai⨁aj.
Calculate the weight of the minimum spanning tree in this graph.
1
≤
n
≤
2
∗
1
0
5
,
1
≤
a
i
≤
1
0
5
1\leq n\leq 2*10^5,1\leq a_i\leq10^5
1≤n≤2∗105,1≤ai≤105
Solution
https://www.luogu.com.cn/problem/solution/CF888G
看 wu3412790 的
另关于复杂度的证明:
trie总共有nlogn个点
每个点中的子树最多遍历nlogn个点
每个点只会被它的父亲遍历到 即最多logn遍
即时间复杂度<
n
l
o
g
2
n
nlog^2n
nlog2n
Code
#include<bits/stdc++.h>
using namespace std;
int n,cnt,rt;
long long ans,sum;
int p[31];
struct data{
int son[2],d;
}tree[6000010];
void link(int x,int y,long long s){
if(tree[x].d==30){
sum=min(sum,s);
return;
}
bool flag=0;
for(int i=0;i<2;i++)
if(tree[x].son[i]&&tree[y].son[i]) {
link(tree[x].son[i],tree[y].son[i],s);
flag=true;
}
if(flag) return;
if(tree[x].son[0]&&tree[y].son[1])
link(tree[x].son[0],tree[y].son[1],s+p[29-tree[x].d]);
else link(tree[x].son[1],tree[y].son[0],s+p[29-tree[x].d]);
}
void dfs(int x){
if(!x||tree[x].d==30) return;
for(int i=0;i<2;i++)
if(tree[x].son[i]) dfs(tree[x].son[i]);
if(tree[x].son[0]&&tree[x].son[1]){
sum=2e9;
link(tree[x].son[0],tree[x].son[1],p[29-tree[x].d]);
ans+=sum;
}
}
void ins(int x){
int u=rt;
for(int i=0;i<30;i++){
int t=(x&p[29-i])>0;
if(!tree[u].son[t]){
tree[u].son[t]=++cnt;
tree[cnt].d=tree[u].d+1;
}
u=tree[u].son[t];
}
}
int main(){
int x;
rt=cnt=p[0]=1;
scanf("%d",&n);
for(int i=1;i<30;i++)
p[i]=p[i-1]*2;
for(int i=1;i<=n;i++){
scanf("%d",&x);
ins(x);
}
//cout<<"pre:ok\n";
dfs(1);
printf("%lld",ans);
}