【CF888G】Xor-MST
题意:给你一张n个点的完全图,每个点有一个权值ai,i到j的边权使ai^aj,求这张图的最小生成树。
n<=200000,ai<2^30
题解:学到了求最小生成树的新姿势。
Boruvka算法:先对于每个点,选择在所有与之相连的边中,权值最小的边,并将这条边加入到最小生成树中。显然这样连出来的边会形成一个森林,并且连边后连通块个数至少减半。然后我们将每个连通块再看成一个点,重复以上算法即可。时间复杂度O(mlogn)。
对于本题,该如何优化呢?不难想到Trie树。我们很容易就能找到对于一个点,它与所有其它连通块中的点的连边中,权值最小的是哪个。然后这题就做完了。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=200010;
ll ans;
int n,m,tot;
int to[maxn],val[maxn],rt[maxn],f[maxn],v[maxn],bel[maxn];
vector<int> p[2][maxn];
vector<int>::iterator it;
struct node
{
int ch[2],siz;
}s[maxn*61];
inline void insert(int &x,int z,int w)
{
if(!x) x=++tot;
int i,u=x,d;
for(i=29;~i;i--)
{
d=(w>>i)&1;
if(!s[u].ch[d]) s[u].ch[d]=++tot;
u=s[u].ch[d],s[u].siz++;
}
s[u].siz=z;
}
inline void query(int x,int y,int z,int w)
{
int i,d,ret=0;
for(i=29;~i;i--)
{
d=(w>>i)&1;
if(s[s[x].ch[d]].siz==s[s[y].ch[d]].siz) d^=1,ret|=(1<<i);
x=s[x].ch[d],y=s[y].ch[d];
}
if(ret<val[z]) val[z]=ret,to[z]=s[x].siz;
}
int find(int x)
{
return (f[x]==x)?x:(f[x]=find(f[x]));
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
}
int main()
{
n=rd();
int i,d=0;
for(i=1;i<=n;i++) v[i]=rd();
sort(v+1,v+n+1);
for(i=1;i<=n;i++) if(i==1||v[i]>v[i-1]) p[0][++m].push_back(v[i]);
while(m>1)
{
n=m,m=0,memset(val,0x3f,sizeof(val[0])*(n+1)),memset(rt,0,sizeof(rt[0])*(n+1));
memset(s,0,sizeof(s[0])*(tot+1)),tot=0;
for(i=1;i<=n;i++) for(it=p[d][i].begin();it!=p[d][i].end();it++) insert(rt[i],i,*it),insert(rt[0],i,*it);
for(i=1;i<=n;i++) for(it=p[d][i].begin();it!=p[d][i].end();it++) query(rt[0],rt[i],i,*it);
for(i=1;i<=n;i++) p[d^1][i].clear(),f[i]=i;
for(i=1;i<=n;i++) if(find(to[i])!=find(i)) f[f[i]]=f[to[i]],ans+=val[i];
for(i=1;i<=n;i++) if(find(i)==i) bel[i]=++m;
for(i=1;i<=n;i++) for(it=p[d][i].begin();it!=p[d][i].end();it++) p[d^1][bel[f[i]]].push_back(*it);
d^=1;
}
printf("%I64d",ans);
return 0;
}