码迷,mamicode.com
首页 > 其他好文 > 详细

[CF888G]Xor-MST

时间:2020-02-07 22:16:54      阅读:84      评论:0      收藏:0      [点我收藏+]

标签:tps   eof   ++   题解   namespace   first   lld   cond   pair   

G - Xor-MST

题解

最小异或生成树
先把所有二进制数上Trie树,然后为了使得异或最小,根据异或的性质,trie树的左右子树都应该自己先连成一个连通块,然后在两个连通块内找到两个数使得异或值最小,这样就能进行连通了。
左右子树的话递归下去处理,在计算两个子树上异或值最小的时候用启发式合并,枚举大小较小的那棵子树的数值,在另外一棵子树上跑。
复杂度\(O(nloglogn)\)
为什么我维护了Trie树的那么多信息??

#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<int,int> PII;
#define X first
#define Y second
inline int read()
{
    int x=0,f=1;char c=getchar();
    while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    return x*f;
}
const int maxn=200010;
int n,v[maxn],ch[32*maxn][2],size[32*maxn],sz,val[maxn*32],L[maxn*32],R[maxn*32],dfn[32*maxn],deep[32*maxn],dfs_clock=1;
void insert(int x)
{
    int now=0;
    for(int i=31;i>=0;i--)
    {
        int c=(x>>i)&1;
        if(!ch[now][c])ch[now][c]=++sz;
        now=ch[now][c];
    }
    val[now]=x;
} 
void dfs(int now)
{
    L[now]=dfs_clock;
    if(val[now])dfn[dfs_clock++]=val[now],size[now]=1;
    for(int i=0;i<2;i++)
        if(ch[now][i])
        {
            deep[ch[now][i]]=deep[now]-1;
            dfs(ch[now][i]);
            size[now]+=size[ch[now][i]];
        }
    R[now]=dfs_clock;
}
int query(int x,int u)
{
    x&=((1<<deep[u])-1);
    int now=u;
    for(int i=deep[u]-1;i>=0;i--)
    {
        int c=(x>>i)&1;
        if(!ch[now][c])c^=1;
        now=ch[now][c];
    }
    return val[now];
}    
LL calc(int u)
{
    if(!ch[u][0] && !ch[u][1])return 0;
    if(!ch[u][0])return calc(ch[u][1]);
    if(!ch[u][1])return calc(ch[u][0]);
    int x=ch[u][0],y=ch[u][1],ans=2147483647;
    if(size[x]>size[y])swap(x,y);
    for(int i=L[x];i<R[x];i++)ans=min(ans,query(dfn[i],y)^dfn[i]);
    return calc(ch[u][0])+calc(ch[u][1])+ans;
}
int main()
{
    n=read();
    for(int i=0;i<n;i++)v[i]=read();
    sort(v,v+n);
    n=unique(v,v+n)-v;
    for(int i=0;i<n;i++)insert(v[i]);
    deep[0]=32;dfs(0); 
    printf("%lld\n",calc(0));
    return 0;
}

[CF888G]Xor-MST

标签:tps   eof   ++   题解   namespace   first   lld   cond   pair   

原文地址:https://www.cnblogs.com/FYH-SSGSS/p/12274694.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!