zoukankan      html  css  js  c++  java
  • [CF888G]Xor-MST

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

    题面

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

    • (nleq2*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
    ",solve(a,30));
      return 0;
    }
    
  • 相关阅读:
    jquery基本用法
    js里BOM和DOM操作
    js基础语法
    java将json格式的字符串转化为对象数组
    Java生成Excel并导入数据
    mybatis的xml中使用foreach循环拼接(sql中的 in 语法)
    FreeMarker在List中取任意一条数据的某一个值
    freemarker中的常用语法
    Java将日期转化为大写格式(阿拉伯大写数字)
    项目中出现The import javax.servlet cannot be resolved 的解决方法
  • 原文地址:https://www.cnblogs.com/yanshannan/p/9496053.html
Copyright © 2011-2022 走看看