You are given a complete undirected graph with n vertices. A number ai is assigned to each vertex, and the weight of an edge between vertices i and j is equal to aixoraj.

Calculate the weight of the minimum spanning tree in this graph.

题目大意:

边权为两端点点权的异或,求一个完全图的最小生成树

Input

The first line contains n (1 ≤ n ≤ 200000) — the number of vertices in the graph.

The second line contains n integers a1, a2, ..., an (0 ≤ ai < 230) — the numbers assigned to the vertices.

Output

Print one number — the weight of the minimum spanning tree in the graph.

Examples
Input

Copy
5
1 2 3 4 5
Output
8
Input

Copy
4
1 2 3 4
Output
8

本题要用到一种求生成树的方法Boruvka

给所有单词维护一颗trie树

按照这种求生成树的方法,我们每一次要在trie中去掉该集合的点,再求最小的边

这样很麻烦,实际上可以在trie树内部合并

首先左右子树中的所有点显然是已经在一个连通块内的。我们只需要在左右子树的联通块中各选出一
个点,连边即可

这样如果左子树存在右子树合并肯定最优,因为他们公共前缀最长

考虑启发式合并当前点的左右子树

枚举关键点数更小的子树的关键点,带入另一个子树求出最小边权

最后在根合并成一颗生成树

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long lol;
vector<lol>Q[];
int ch[][],pos,dep[],n;
lol pw[],ans,a[];
void insert(lol x)
{int i;
int now=;
Q[now].push_back(x);
for (i=;i>=;i--)
{
int flag=(bool)((x>>i)&);
if (ch[now][flag]==) ch[now][flag]=++pos;
now=ch[now][flag];
x-=flag*pw[i];
Q[now].push_back(x);dep[now]=i;
}
}
lol merge(int x,lol t)
{int i;
lol as=;
for (i=dep[x]-;i>=;i--)
{
int flag=(bool)((t>>i)&);
if (ch[x][flag]) x=ch[x][flag];
else as+=pw[i],x=ch[x][!flag];
}
return as;
}
lol query(int rt)
{int i;
if (Q[rt].size()==) return ;
if (ch[rt][]) ans+=query(ch[rt][]);
if (ch[rt][]) ans+=query(ch[rt][]);
if (!ch[rt][]||!ch[rt][]) return ;
int flag=;
if (Q[ch[rt][]].size()>Q[ch[rt][]].size()) flag=;
int sz=Q[ch[rt][flag]].size();
lol tmp=2e15;
for (i=;i<sz;i++)
tmp=min(tmp,merge(ch[rt][flag^],Q[ch[rt][flag]][i]));
return tmp+pw[dep[rt]-];
}
int main()
{int i;
cin>>n;
pw[]=;
for (i=;i<=;i++)
pw[i]=pw[i-]*;
for (i=;i<=n;i++)
{
scanf("%lld",&a[i]);
}
sort(a+,a+n+);
n=unique(a+,a+n+)-a-;
for (i=;i<=n;i++)
{
insert(a[i]);
}
ans+=query();
printf("%lld\n",ans);
}

首先左右子树中的所有点显然是已经在一个连通块内的。我们只需要在左右子树的联通块中各选出一
个点,连边即可

codeforces 888G Xor-MST的更多相关文章

  1. Codeforces.888G.Xor-MST(Borůvka算法求MST 贪心 Trie)

    题目链接 \(Description\) 有一张\(n\)个点的完全图,每个点的权值为\(a_i\),两个点之间的边权为\(a_i\ xor\ a_j\).求该图的最小生成树. \(n\leq2*10 ...

  2. Codeforces 888G Xor-MST - 分治 - 贪心 - Trie

    题目传送门 这是一条通往vjudge的高速公路 这是一条通往Codeforces的高速公路 题目大意 给定一个$n$阶完全图,每个点有一个权值$a_{i}$,边$(i, j)$的权值是$(a_{i}\ ...

  3. codeforces 22E XOR on Segment 线段树

    题目链接: http://codeforces.com/problemset/problem/242/E E. XOR on Segment time limit per test 4 seconds ...

  4. Xor-MST Codeforces - 888G

    https://codeforces.com/contest/888/problem/G 这题可以用Boruvka算法: 一开始每个点是一个连通块.每次迭代对于每个连通块找到其最近邻居(与其有边相连且 ...

  5. Codeforces 627A XOR Equation(思路)

    题目大概说两个正整数a.b,已知s=a+b以及x=a xor b的值,问有几种a.b这样的数对. 我知道异或相当于无进位的加法,s-x就是其各个位置的进位,比如s-x=1010,那就表示a和b的第1位 ...

  6. CodeForces 242E - XOR on Segment 二维线段树?

    今天练习赛的题....又是线段树的变换..拿到题我就敲了个点更新区间查询的..果断超时...然后想到了可以将每个数与合表示成不进位的二进制数..这样就可以区间进行更新了..比赛的时候写搓了..刚重写了 ...

  7. codeforces 242E. XOR on Segment 线段树

    题目链接 给n个数, 两种操作, 一种是求区间内的数的和, 一种是将区间内的数异或x. 异或x没有什么思路, 单个异或肯定超时, 区间异或也没有办法做....后来才知道可以按位建线段树, 这样建20棵 ...

  8. Codeforces 888G(分治+trie)

    按位贪心,以当前考虑位是0还是1将数分成两部分,则MST中这两部分之间只会存在一条边,因为一旦有两条或以上的边,考虑两条边在原图中所成的环,显然这两条边有一条是环上的权值最大边,不会出现在MST中.则 ...

  9. codeforces 242E - XOR on Segment (线段树 按位数建树)

    E. XOR on Segment time limit per test 4 seconds memory limit per test 256 megabytes input standard i ...

随机推荐

  1. 第六次作业:Alpha阶段综合报告(Java-Team)

    团队:Java-Team 成员: 章辉宇(284) 吴政楠(286) 陈阳(PM:288) 韩华颂(142) 胡志权(143) github地址:https://github.com/WHUSE201 ...

  2. electron-vue工程创建

    没有vue创建经验请移步至 vue下载与安装 使用vue创建electron-vue工程 vue init simulatedgreg/electron-vue my-project 安装elemen ...

  3. 201621123031 《Java程序设计》第10周学习总结

    作业10-异常 1.本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 1.捕捉异常 Java中的异常捕获结构由try.catch和finally三个部分组成.其中try语句 ...

  4. iOS 简易无限滚动的图片轮播器-SDCycleScrollView

    @interface ViewController () <</span>SDCycleScrollViewDelegate> @end @implementation Vie ...

  5. python解释NTFS runlist的代码(文章转自北亚数据恢复张宇工程师)

    代码如下: 执行效果如下:root@zhangyu-VirtualBox:~/NTFS-5# python3 read_runlist.py mft_source.img ***参数数量或格式错误! ...

  6. vue下拉列表

    最近在弄作品,做了个下拉列表.心想各位小哥哥.小姐姐可能会用到相同的需求,就把下拉列表封装一下,希望能对各位小哥哥,小姐姐有帮助 github地址:https://github.com/ClmPisc ...

  7. 电子称DIY(贴应变片+写代码)

    第一步.应变片介绍   ---------------------------------------------------------------------------------------- ...

  8. Lock(三)查看是谁把表给锁了

    查看是谁把表给锁了 select se1.inst_id as 被阻塞的会话节点, se2.inst_id as 罪魁祸首节点, se1.sid as 被阻塞的会话ID, ob.object_name ...

  9. Web移动端适配总结

    移动端适配的相关概念以及几种方案总结 适配相关概念 布局视口(layout viewport):html元素的上一级容器即顶级容器,用于解决页面在手机上显示的问题.大部分移动设备都将这个视口分辨率设置 ...

  10. window.open()参数详解及对浏览器的兼容性

    因为篇幅,window.open()浏览器的兼容性请点击 这里 Part1:参数详解 window.open(url,name,param) url:即将打开的子窗口的地址:比如 "http ...