zoukankan      html  css  js  c++  java
  • CF888G XOR-MST trie,贪心

    CF888G XOR-MST

    链接

    CF888G

    思路

    trie上贪心,先左右两边连边,再用一条边的代价连起左右两颗树。因为内部的边一定比跨两棵树的边权笑,显然是对的。
    代码自己瞎yy的。启发式合并

    代码

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int _=2e5+7;
    int n,a[_],ch[_*30][2],siz[_*30],cnt,col,rt[_*30];
    ll ans;
    std::vector<int> dsr[_*30];
    void insert(int x) {
    	int p=0;
    	for(int i=29;i>=0;--i) {
    		bool k=x&(1LL<<i);
    		siz[p]++;
    		if(!ch[p][k]) ch[p][k]=++cnt;
    		p=ch[p][k];
    	} siz[p]++;
    	if(!rt[p]) rt[p]=++col;
    	dsr[rt[p]].push_back(x);
    }
    int query(int rt,int init,int x) {
    	int p=rt,ans=0;
    	for(int i=init;i>=0;--i) {
    		bool k=x&(1LL<<i);
    		if(ch[p][k]) p=ch[p][k];
    		else p=ch[p][!k],ans|=1<<i;
    	}
    	return ans;
    }
    void dfs(int p,int dep) {
    	if(!ch[p][0]&&!ch[p][1]) return;
    	if(!ch[p][0]||!ch[p][1]) {
    		dfs(ch[p][0]|ch[p][1],dep-1);
    		rt[p]=rt[ch[p][0]|ch[p][1]];
    	} else {
    		int k=siz[ch[p][0]]<siz[ch[p][1]];
    		dfs(ch[p][0],dep-1),dfs(ch[p][1],dep-1);
    		rt[p]=rt[ch[p][k]];
    		int tmp=0x3f3f3f3f;
    		int nb=ch[p][!k];
    		ch[p][!k]=0;
    		for(auto x:dsr[rt[nb]]) {
    			tmp=min(tmp,query(p,dep,x));
    			dsr[rt[p]].push_back(x);
    		}
    		ans+=tmp;
    		ch[p][!k]=nb;
    	}
    }
    int main() {
    	// freopen("a.in","r",stdin);
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i) scanf("%d",&a[i]),insert(a[i]);
    	dfs(0,29);
    	cout<<ans<<"
    ";
    	return 0;
    }
    
  • 相关阅读:
    四则运算1
    四则运算3
    数组1
    四则运算单元测试
    四则运算2
    数组3
    数组2
    spring aop对service层日志和异常的处理
    Linux设置开机启动
    数据仓库开发——Kettle使用示例
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/11379895.html
Copyright © 2011-2022 走看看