zoukankan      html  css  js  c++  java
  • 【Trie】MIPT-2016 Pre-Finals Workshop, Taiwan NTU Contest, Sunday, March 27, 2016 Problem B. Be Friends

    题意:一个n个点的完全图,点带权,边权是两端点点权的异或值。问你最小生成树。

    一个性质,把所有点按照二进制最高位是否为1划分为2个集合,那么这两个集合间只会有一条边。可以递归处理。

    把所有点建成01Trie,发现两个集合就是Trie的每个结点的两个子树。用启发式的思想,在小子树里dfs到叶子结点,取出每个值,然后去大子树里查询即可。

    O(n(logn)^2)。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int ch[100005*32][2],sz,siz[100005*32];
    void Insert(int x)
    {
        int U=0;
        for(int i=31-1;i>=0;--i){
    		if(!ch[U][(x>>i)&1]){
    			ch[U][(x>>i)&1]=++sz;
    		}
    		U=ch[U][(x>>i)&1];
    	}
    }
    int query(int x,int U,int nidep){
    	int res=0;
    	for(int i=nidep;i>=0;--i){
    		bool Bit=((x>>i)&1);
    		if(!ch[U][Bit]){
    			res|=(1<<i);
    			Bit^=1;
    		}
    		U=ch[U][Bit];
    	}
    	return res;
    }
    ll ans;
    void dfsz(int U){
    	if(!ch[U][0] && !ch[U][1]){
    		siz[U]=1;
    	}
    	if(ch[U][0]){
    		dfsz(ch[U][0]);
    		siz[U]+=siz[ch[U][0]];
    	}
    	if(ch[U][1]){
    		dfsz(ch[U][1]);
    		siz[U]+=siz[ch[U][1]];
    	}
    }
    int nowans;
    void df2(int U,int now,int rtnidep,int nidep,int otherrt){
    	if(!ch[U][0] && !ch[U][1]){
    		nowans=min(nowans,query(now,otherrt,rtnidep-1));
    	}
    	if(ch[U][0]){
    		df2(ch[U][0],now,rtnidep,nidep-1,otherrt);
    	}
    	if(ch[U][1]){
    		df2(ch[U][1],now|(1<<(nidep-1)),rtnidep,nidep-1,otherrt);
    	}
    }
    void dfs(int U,int nidep){
    	if(ch[U][0] && ch[U][1]){
    		nowans=2147483647;
    		if(siz[ch[U][0]]>siz[ch[U][1]]){
    			df2(ch[U][1],0,nidep,nidep,ch[U][0]);
    		}
    		else{
    			df2(ch[U][0],0,nidep,nidep,ch[U][1]);
    		}
    		nowans|=(1<<nidep);
    		ans+=nowans;
    	}
    	if(ch[U][0]){
    		dfs(ch[U][0],nidep-1);
    	}
    	if(ch[U][1]){
    		dfs(ch[U][1],nidep-1);
    	}
    }
    int n,m;
    int main(){
    //	freopen("b.in","r",stdin);
    	int x;
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i){
    		scanf("%d",&x);
    		Insert(x);
    	}
    	dfsz(0);
    	dfs(0,30);
    	printf("%lld
    ",ans);
    	return 0;
    }
  • 相关阅读:
    组合与封装
    继承与派生
    面向对象编程
    subprocess、re、logging模块
    json、pickle、collections、openpyxl模块
    python内置模块
    递归函数与模块
    生成式、面向过程、与函数式
    叠加装饰器与迭代器
    闭包函数与装饰器
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7422284.html
Copyright © 2011-2022 走看看