【CF888G】Xor-MST(生成树 Trie)
大意
给出\(N\)个点的点权,定义两个点之间的边权为这两个点权的异或和,求这\(N\)个点间的最小生成树。
思路
贪心地想,相连的两个点异或和应当尽量的小。
那么应先从高位确定,因为高位的大小比低位大,所以高位间的连边首先要尽量小。
考虑对于某一数位怎么做:
首先将这一位的数字全部抽出来,变成一个01串。
明显0应先和0连,1应先和1连,最后留出一条0和1间的连边要尽量小。
那么全0和全1的部分就又可以分治到下一个数位去了。
考虑0和1间的连边怎么做:
那么我们对于0和1中的某个集合中的某个数,把它拿到另外一个数集中去比较,
从高位往下比,每位尽量贴近该数,对于每个数都这样操作然后取较小值就可以得到这条边了。
注:
- 找数可以用Trie树实现。
- 时间复杂度根据实现不同在\(O(N\cdot log(N))\)与\(O(N\cdot log(N)^2)\)之间。
代码
#include<queue>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXK=3;
const int MAXN=200005;
const int INF=2e9;
int N,A[MAXN],Cnt;
long long Ans;
struct Node{
int dep,L,R;
int ch[MAXK];
}s[MAXN*40];
void Push_Up(int rt){
if(s[rt].ch[0]&&s[rt].ch[1]){
s[rt].L=min(s[s[rt].ch[0]].L,s[s[rt].ch[1]].L);
s[rt].R=max(s[s[rt].ch[0]].R,s[s[rt].ch[1]].R);
}
else if(s[rt].ch[0])s[rt].L=s[s[rt].ch[0]].L,s[rt].R=s[s[rt].ch[0]].R;
else if(s[rt].ch[1])s[rt].L=s[s[rt].ch[1]].L,s[rt].R=s[s[rt].ch[1]].R;
}
void Insert(int rt,int val,int k,int id){
s[rt].dep=k;
if(k==-1){s[rt].L=s[rt].R=id;return ;}
int u=(1&(val>>k));
if(!s[rt].ch[u])s[rt].ch[u]=++Cnt;
Insert(s[rt].ch[u],val,k-1,id);
Push_Up(rt);
}
long long query(int rt,int x){
long long ret=0;
for(int i=s[rt].dep;i>=0;i--){
int u=((x>>i)&1);
if(s[rt].ch[u])rt=s[rt].ch[u];
else ret+=(1<<i),rt=s[rt].ch[!u];
}
return ret;
}
long long DFS(int rt){
long long ret=0;
if(s[rt].ch[0])ret+=DFS(s[rt].ch[0]);
if(s[rt].ch[1])ret+=DFS(s[rt].ch[1]);
if(s[rt].ch[0]&&s[rt].ch[1]){
long long tmp=INF;
int ls=s[rt].ch[0],rs=s[rt].ch[1];
for(int i=s[ls].L;i<=s[ls].R;i++)
tmp=min(tmp,query(rs,A[i]));
ret+=tmp+(1<<s[rt].dep);
}
return ret;
}
int main(){
scanf("%d",&N);
for(int i=1;i<=N;i++)
scanf("%d",&A[i]);
sort(A+1,A+N+1);
for(int i=1;i<=N;i++)
Insert(0,A[i],30,i);
printf("%lld\n",DFS(0));
}
【CF888G】Xor-MST(生成树 Trie)的更多相关文章
- Codeforces.888G.Xor-MST(Borůvka算法求MST 贪心 Trie)
题目链接 \(Description\) 有一张\(n\)个点的完全图,每个点的权值为\(a_i\),两个点之间的边权为\(a_i\ xor\ a_j\).求该图的最小生成树. \(n\leq2*10 ...
- [USACO]6.1.3 cow xor(二进制+Trie)
题意:给你一个序列(n<=100000),求出一个连续的子序列[i,j]使得ai xor ai+1 xor…… xor aj最大,求出这个最大值(其中每个数<=2^21) 分析:题目和求一 ...
- 【xsy1147】 异或(xor) 可持久化trie
我的脑回路可能比较奇怪. 我们对这些询问离线,将所得序列${a}$的后缀和建$n$棵可持久化$trie$. 对于一组询问$(l,r,x)$,我们在主席树上询问第$l$棵树$-$第r$+1$棵树中与$s ...
- The XOR Largest Pair [Trie]
描述 在给定的N个整数A1,A2--AN中选出两个进行xor运算,得到的结果最大是多少? 输入格式 第一行一个整数N,第二行N个整数A1-AN. 输出格式 一个整数表示答案. 样例输入 3 1 2 3 ...
- hdu 5269 ZYB loves Xor I 分治 || Trie
题目大意: 长度为\(n\)的数组A.求对于所有数对\((i,j)(i \in [1,n],j \in [1,n])\),\(lowbit(A_i xor A_j)\)之和.答案对998244353取 ...
- HDU 4825 Xor Sum (trie树处理异或)
Xor Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others)Total S ...
- 计蒜客15430 XOR Queries(Trie处理位运算问题)
题意: 给出一个长度为n的数组C,回答m个形式为(L, R, A, B)的询问, 含义为存在多少个不同的数组下标k属于[L, R]满足C[k] XOR A >= B(式中XOR为异或运算). T ...
- HDU 4825:Xor Sum(Trie)
http://acm.hdu.edu.cn/showproblem.php?pid=4825 题意:给出N个数,M个询问,每个询问给出一个X,问在这N个数中哪个数和X异或后结果最大. 思路:可以用Tr ...
- UVALive 4682 XOR Sum (trie)
题意:求一段连续的数字使得它们的异或和最大. 思路:首先利用前缀和求sum[i],这样求某段连续数字异或和最大就是求某两个j和i满足sum[i]^sum[j-1]最大,问题就变成了找两个数的异或最大. ...
随机推荐
- C# UTF8的BOM导致XML序列化与反序列化报错:Data at the root level is invalid. Line 1, position 1.
最近在写一个xml序列化及反序列化实现时碰到个问题,大致类似下面的代码: class Program { static void Main1(string[] args) { var test = n ...
- 访问局域网内其他主机的VMware虚拟机上的mysql数据库和redis缓存
上一篇写了访问局域网内其他主机的虚拟机上的项目 ,现在说说访问局域网内其他主机的虚拟机上的数据库和缓存 博主使用的linux是Ubuntu16.04: 一.安装数据库和缓存 这里连接的数据库和缓存以m ...
- “老”的Flexbox和“新”的Flexbox
本文由大漠根据Chris Coyier的<"Old" Flexbox and "New" Flexbox>所译,整个译文带有我们自己的理解与思想,如 ...
- 揭秘 BPF map 前生今世
揭秘 BPF map 前生今世 本文地址:https://www.ebpf.top/post/map_internal 1. 前言 众所周知,map 可用于内核 BPF 程序和用户应用程序之间实现双向 ...
- HTTP2和WebSocket
HTTP http是目前应用最广泛的应用层协议,截止到目前为止已经发布了多个版本,最常用的是http1.1和http2. http0.9是最早的版本,功能很简单,没有header,只支持GET. ht ...
- markdownFormat
对文档编辑主要还是用wps,因为以前毕业论文都是用的它来编排(刚开始用wps毕业论文的时候真的是用的想吐,感觉非常不好用,而且功能太多但对于自己需要的功能又偏偏找不到),用过几次后还觉得用它编辑文 ...
- Java中生成一个唯一值的方式
现总结几种生成一个唯一值的方式 第一种:采用nanoTime() // 理论上存在重复的可能,可以在后面再加上一个随机字符串 Random r = new Random(); for (int i = ...
- windos 安装 redis 启动闪退
本来想在linux上安装redis的,后来觉得也没必要,主要是了解使用方法,和原理,在什么平台上安装都是大同小异的 接下来简单描述下碰到的小问题:闪退和启动失败 究其原因就是端口被占用了,但是自己并没 ...
- Java基础(十)——枚举与注解
一.枚举 1.介绍 枚举类:类的对象只有有限个,确定的.当需要定义一组常量时,强烈建议使用枚举类.如果枚举类中只有一个对象,则可以作为单例模式的实现. 使用 enum 定义的枚举类默认继承了 java ...
- ES6随笔D1
1.数值解构赋值 ES6 允许按照一定模式,可以从数组中提取值,按照对应位置,对变量赋值,这被称为解构. 解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象.由于undefined和n ...