题意

题目链接

给出\(n\)点,每个点有一个点权\(a[i]\),相邻两点之间的边权为\(a[i] \oplus a[j]\),求最小生成树的值

Sol

非常interesting的一道题,我做过两种这类题目,一种是直接打表找规律,另一种就像这种用Boruvka算法加一些骚操作来搞。

首先,把所有元素扔到Trie树里面,这样对于Trie树上的每一层(对应元素中的每一位)共有两种情况:

  1. 全为0或全为1

  2. 一部分为0另一部分为1

对于第一种情况,我们无需考虑,因为任意点相邻产生的贡献都是0,对于第二种情况,需要找到一条最小的边来连接链各个集合,这可以在Trie树上贪心实现

另外还有一个小Trick,我们把元素从小到大排序,这样Trie树上每个节点对应的区间就都是连续的

实现的时候可以从底往上update,也可以从上往下dfs

时间复杂度:\(O(nlognlog_{max(a_i)})\)

本来以为这题要写一年,结果写+调只用了1h不到?

#include<bits/stdc++.h>
#define Pair pair<int, int>
#define fi first
#define se second
#define MP(x, y) make_pair(x, y)
#define LL long long
using namespace std;
const int MAXN = 2e5 + 10, B = 31, INF = 1e9 + 7;
inline LL read() {
char c = getchar(); LL x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int N, a[MAXN], L[MAXN * 30], R[MAXN * 30], ch[MAXN * 30][2], tot = 0;
void insert(int val, int pos) {
int now = 0;
for(int i = B; ~i; i--) {
int x = val >> i & 1;
if(!ch[now][x]) ch[now][x] = ++tot, L[tot] = pos, R[tot] = pos;//???ʵ???֮?????λ
L[now] = min(L[now], pos); R[now] = max(R[now], pos);
now = ch[now][x];
}
}
int Query(int val, int now, int NowBit) {
LL ans = 1 << (NowBit + 1);
for(int i = NowBit; ~i; i--) {
int x = val >> i & 1;
if(ch[now][x]) now = ch[now][x];
else ans |= 1 << i, now = ch[now][x ^ 1];
}
return ans;
}
LL dfs(int x, int NowBit) {
LL res = 0;
if(NowBit == 0)
return (ch[x][0] && ch[x][1]) ? (a[L[ch[x][0]]] ^ a[R[ch[x][1]]]) : 0;
//if(NowBit == 0) return ;
if(ch[x][0] && ch[x][1]) {
int tmp = INF;
for(int i = L[ch[x][0]]; i <= R[ch[x][0]]; i++) tmp = min(tmp, Query(a[i], ch[x][1], NowBit - 1));
res += tmp;
}
if(ch[x][0]) res += dfs(ch[x][0], NowBit - 1);
if(ch[x][1]) res += dfs(ch[x][1], NowBit - 1);
return res;
}
int main() {
N = read();
for(int i = 1; i <= N; i++) a[i] = read();
sort(a + 1, a + N + 1);
L[0] = INF; R[0] = 0;
for(int i = 1; i <= N; i++) insert(a[i], i);
cout << dfs(0, B);
return 0;
}

cf888G. Xor-MST(Boruvka最小生成树 Trie树)的更多相关文章

  1. 51nod 1295 XOR key (可持久化Trie树)

    1295 XOR key  题目来源: HackerRank 基准时间限制:1.5 秒 空间限制:262144 KB 分值: 160 难度:6级算法题   给出一个长度为N的正整数数组A,再给出Q个查 ...

  2. 51nod 1295 XOR key | 可持久化Trie树

    51nod 1295 XOR key 这也是很久以前就想做的一道板子题了--学了一点可持久化之后我终于会做这道题了! 给出一个长度为N的正整数数组A,再给出Q个查询,每个查询包括3个数,L, R, X ...

  3. CodeForces979D:Kuro and GCD and XOR and SUM(Trie树&指针&Xor)

    Kuro is currently playing an educational game about numbers. The game focuses on the greatest common ...

  4. The XOR Largest Pair (trie树)

    题目描述 在给定的 NN 个整数 A_1,A_2,--,A_NA1​,A2​,--,AN​ 中选出两个进行xor运算,得到的结果最大是多少?xor表示二进制的异或(^)运算符号. 输入格式 第一行输入 ...

  5. BZOJ5338 [TJOI2018] Xor 【可持久化Trie树】【dfs序】

    题目分析: 很无聊的一道题目.首先区间内单点对应异或值的询问容易想到trie树.由于题目在树上进行,case1将路径分成两段,然后dfs的时候顺便可持久化trie树做询问.case2维护dfs序,对d ...

  6. CH1602 The XOR Largest Pair【Trie树】

    1602 The XOR Largest Pair 0x10「基本数据结构」例题 描述 在给定的N个整数A1,A2……AN中选出两个进行xor运算,得到的结果最大是多少? 输入格式 第一行一个整数N, ...

  7. CODEVS1187 Xor最大路径 (Trie树)

    由于权值是在边上,所以很容易发现一个性质:d(x,y)=d(x,root) xor d(y,root). 因为有了这个性质,那么就很好做了.对于每一个点统计到root的距离,记为f 数组. 将f数组里 ...

  8. 【CF888G】Xor-MST Trie树(模拟最小生成树)

    [CF888G]Xor-MST 题意:给你一张n个点的完全图,每个点有一个权值ai,i到j的边权使ai^aj,求这张图的最小生成树. n<=200000,ai<2^30 题解:学到了求最小 ...

  9. 【CF888G】Xor-MST(最小生成树,Trie树)

    [CF888G]Xor-MST(最小生成树,Trie树) 题面 CF 洛谷 题解 利用\(Kruskal\)或者\(Prim\)算法都很不好计算. 然而我们还有一个叫啥来着?\(B\)啥啥的算法,就叫 ...

随机推荐

  1. Map/Reduce应用开发基础知识-摘录

    Map/Reduce 这部分文档为用户将会面临的Map/Reduce框架中的各个环节提供了适当的细节.这应该会帮助用户更细粒度地去实现.配置和调优作业.然而,请注意每个类/接口的javadoc文档提供 ...

  2. 17、OpenCV Python 数字验证码识别

    __author__ = "WSX" import cv2 as cv import numpy as np from PIL import Image import pytess ...

  3. File 文件操作类 大全

    File  文件操作类  大全 许多人都会对文件操作感到很难  我也是  但是一个好的项目中必定会涉及到文件操作的 文件的复制 粘贴  等等等 公司大佬写了 一个文件操作的工具类 感觉还是棒棒的啦   ...

  4. EA添加时序图

    在项目浏览器的空白处右击 http://blog.csdn.net/craftsman1970/article/details/70877530 不同于大部分面向对象或者UML的书籍,在讨论完类图/对 ...

  5. POJ3322 Bloxorz I 无脑广搜(我死了。。。)

    多测不清空,爆零两行泪....我死了QWQ 每个节点3个状态:横坐标,纵坐标,和方向 说一下方向:0:立着,1:竖着躺着,上半部分在(x,y),2:横着躺着,左半部分在(x,y) 然后就有了常量数组: ...

  6. zoj4062 Plants vs. Zombies 二分+模拟(贪心的思维)

    题目传送门 题目大意:有n个植物排成一排,标号为1-n,每株植物有自己的生长速度ai,每对植物浇一次水,该株植物就长高ai,现在机器人从第0个格子出发,每次走一步,不能停留,每一步浇一次水,总共可以走 ...

  7. 简单易懂的VS-CODE C++环境配置(ACM向)

    网上教程比较繁琐,他们似乎要把vs-code变得无所不能,而我只是想代替dev进行简单的输入输出 所以大概花了1个多小时找到了能用的方法(中途还搞了个ubuntu子系统发现没啥用) 这里随便说下 1. ...

  8. PHPExcel 读取的几个例子

    1.使用 PHPExcel_IOFactory 读取文件 $objPHPExcel = PHPExcel_IOFactory::load($inputFileName); 2.使用一个特定的读取类,读 ...

  9. [转] 从零开始学Spring Boot

    [From] http://412887952-qq-com.iteye.com/blog/2291496 一个博主写的spring boot系列文章,很赞!

  10. Ubuntu 15.04 下apt-get安装JDK

    [From] http://blog.csdn.net/skykingf/article/details/45250017 1.删除自带的OpenJDK [python] view plain cop ...