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

    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
    ",calc(0));
    	return 0;
    }
    
  • 相关阅读:
    ciancd开源
    Deployment Pipeline using Docker, Jenkins, Java
    Jenkins与.NET项目
    设置jenkins代理
    p4 是否能自动merge
    jenkins和docker 使用docker作为slave
    jenkins插件 build timeout和build timestamp
    jenkins 插件开发资料
    jenkins2 pipeline 语法快速参考
    jenkins2 pipeline插件的10个最佳实践
  • 原文地址:https://www.cnblogs.com/FYH-SSGSS/p/12274694.html
Copyright © 2011-2022 走看看