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. 极光征文 | 写写文章就能赢 Filco,岂不美滋滋

    由极光社区举办的第二届征文大赛 --「我和极光的那些事儿」又来啦! 在简书平台发布文章并投稿至「我和极光的那些事」专题,只要参与就能 100% 获得京东购物卡,更有机会赢取象征信仰的 Filco 机械 ...

  2. Beta 凡事预则立

    写在Beta冲刺前 关于组长是否重选的议题和结论 总体结论 组长无需更换 队内无人替代 理由 当前组长能够较好的号召和组织团队成员进行工作 当前组长能够对项目有合理的规划 当前组长被大家一致认可可以继 ...

  3. C语言博客作业—字符数组

    一.PTA实验作业 题目1:字符串转换成十进制整数 1. 本题PTA提交列表 2. 设计思路 (1)定义i为循环变量,number用于存放每一次转化的结果,flag用于判断是否为负数,p用于修改结果的 ...

  4. Beta敏捷冲刺每日报告——Day5

    1.情况简述 Beta阶段Scrum Meeting 敏捷开发起止时间 2017.11.6 00:00 -- 2017.11.7 00:00 讨论时间地点 2017.11.6 早9:30,电话会议会议 ...

  5. 学号:201621123032 《Java程序设计》第13周学习总结

    1:本周学习总结 2:为你的系统增加网络功能(购物车.图书馆管理.斗地主等)-分组完成 2.1:简述你想为你的系统增加什么网络功能?设计思路是什么? 创建了一个服务器监听8080端口,通过网络助手客户 ...

  6. 第14、15週PTA題目的處理

    題目1 選擇法排序 1.實驗代碼 #include <stdio.h> #include <stdlib.h> int main() { int n,index,exchang ...

  7. Vue filter介绍及详细使用

    Vue filter介绍及其使用 VueJs 提供了强大的过滤器API,能够对数据进行各种过滤处理,返回需要的结果. Vue.js自带了一些默认过滤器例如: capitalize 首字母大写 uppe ...

  8. 前端面试题:JS中的let和var的区别

    最近很多前端的朋友去面试被问到let和var的区别,其实阮一峰老师的ES6中已经很详细介绍了let的用法和var的区别.我简单总结一下,以便各位以后面试中使用. ES6 新增了let命令,用来声明局部 ...

  9. php中(包括织梦cms)set_time_limit(0)不起作用的解决方法

    背景介绍: 在做织梦冗余图片清理的功能时, 由于冗余图片太多,导致每次清理时都会超时, 后来在网上搜索了各种文章,网上有如下的解决方法: set_time_limit(0) ini_set('max_ ...

  10. EasyUI 中datagrid 分页。

    注释:datagrid分页搞了好几天才完全搞好,网上没完全的资料.明天晚上贴代码. 睡觉.