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;
    }
    
  • 相关阅读:
    2015-05-06前端开发总结
    深入了解 Flexbox 伸缩盒模型
    Sublime text3 快捷方式(windows平台)
    移动web最简洁的滑动效果Swipe JS(适合初学者)
    谈响应式web设计代码实现
    经验分享:多屏复杂动画CSS技巧三则
    css3 animation动画效果解析
    移动H5前端性能优化指南
    php codeigniter (CI) oracle 数据库配置-宋正河整理
    jquery图片裁切+PHP文件上传
  • 原文地址:https://www.cnblogs.com/FYH-SSGSS/p/12274694.html
Copyright © 2011-2022 走看看