[CF888G]Xor-MST

https://www.zybuluo.com/ysner/note/1253739

题面

给定一个\(n\)个节点的完全图,每个节点有个编号\(a_i\),节点\(i\)和节点\(j\)之间边的权值为\(a_i\bigoplus a_j\),求该图的最小生成树的权值和。

  • \(n\leq2*10^5\)

    解析

    有个新奇的最小生成树算法:
    \(Boruvka\)算法:
    先对于每个点,选择在所有与之相连的边中,权值最小的边,并将这条边加入到最小生成树中。
    显然这样连出来的边会形成一个森林,并且连边后连通块个数至少减半。
    然后我们将每个连通块再看成一个点,重复以上算法即可。
    时间复杂度\(O(mlogn)\)

从高位往低位贪心。
把所有点按当前位为\(0\)还是\(1\)分为两类。
显然这两类内部会形成联通块。

然后这两类间一定会有连边。
根据上面那个算法,如果我们选出两类数之间边权最小的那条边,这条边一定在最小生成树中。
因为这是当前状态下(两个大连通块)运行\(B\)算法后将得到的结果。
接下来分治对两类数内部进行处理。

找边权最小值,直接\(Trie\)树即可。

总复杂度\(O(mlogn)\)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#define re register
#define il inline
#define ll long long
#define pb push_back
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define fp(i,a,b) for(re int i=a;i<=b;i++)
#define fq(i,a,b) for(re int i=a;i>=b;i--)
using namespace std;
const int mod=1e9+7,N=2e5+100;
int n,tot,rt,t[N<<5][2];
il ll gi()
{
   re ll x=0,t=1;
   re char ch=getchar();
   while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
   if(ch=='-') t=-1,ch=getchar();
   while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
   return x*t;
}
il void Insert(re int &u,re int x,re int d)
{
  if(!u) u=++tot,t[u][0]=t[u][1]=0;
  if(d<0) return;
  Insert(t[u][(x>>d)&1],x,d-1);
}
il int Query(re int u,re int x,re int d)
{
  if(d<0) return 0;re int c=(x>>d)&1;
  if(t[u][c]) return Query(t[u][c],x,d-1);
  if(t[u][c^1]) return Query(t[u][c^1],x,d-1)^(1<<d);
  return 0;
}
il ll solve(vector<int>a,re int d)
{
  if(!a.size()||d<0) return 0;
  vector<int>b[2];re int mn=0;
  for(re int i=0;i<a.size();i++) b[(a[i]>>d)&1].pb(a[i]);
  if(b[0].size()&&b[1].size())
    {
      tot=rt=0;mn=1<<(d+1);
      for(re int i=0;i<b[0].size();i++) Insert(rt,b[0][i],30);
      for(re int i=0;i<b[1].size();i++) mn=min(mn,Query(rt,b[1][i],30));
    }
  return mn+solve(b[0],d-1)+solve(b[1],d-1);
}
int main()
{
  n=gi();vector<int>a;
  fp(i,1,n) a.pb(gi());
  printf("%lld\n",solve(a,30));
  return 0;
}

猜你喜欢

转载自www.cnblogs.com/yanshannan/p/9496053.html