题解:CF888G Xor-MST
题解:CF888G Xor-MST
题目大意:给定 \(n\) 个点的点权, 任意两点间边权是点权的异或和。求这张完全图的 MST 的权值。
思路:
Boruvka + Trie树 + 按位贪心。
关键就在于如何求出 Boruvka 中的 best 数组。
考虑对点权建 trie 树,对于节点 \(i\) 本轮的连边,就是找 “和它最相似” 的那个。
我最初的想法是只建一棵 trie 树,那么上述过程只需要每次 尽量 按照 \(a[i]\) 来走就行,但接着就发现不太对,因为求不出 "除去 \(i\) 所在集合中的点权 的影响后的最好方案"。
参考了这篇博客 ,发现给 全局 和 每个集合 分别建树是个很妙的想法,这样就可以轻松减去本集合的权值。具体实现是记录一个 siz 数组。
建树,统计答案都已经实现了,最后合并一下两棵树的信息就行。
感觉难点就在于理清楚思路。比较难写的是merge和query,细节比较多。
时间复杂度 \(O(30nlogn)\)
#include<bits/stdc++.h>
#define F(i,l,r) for(int i(l);i<=r;++i)
#define G(i,r,l) for(int i(r);i>=l;--i)
#define pii pair<int, int>
#define fi first
#define se second
using ll = long long;
using namespace std;
const int N = 2e5 +5;
const ll inf = 0x3f3f3f3f;
int a[N], fa[N], best[N], ch[50 * N][2], val[N], root[N], siz[50 * N], tail[50 * N];
int n, num = 0;
inline int get(int x){
return (fa[x]==x) ? x : fa[x] = get(fa[x]);
}
void insert(int &uu, int idx, int w){
if(!uu) uu = ++num;
int u = uu;
G(i, 30, 0){
int o = w >> i & 1;
siz[u] ++ ;
if(!ch[u][o]) ch[u][o] = ++num;
u = ch[u][o];
}
tail[u] = idx; siz[u] = 1;
}
void merge(int &p, int q){
if(!p || !q) return (void)(p = p + q);
merge(ch[p][0], ch[q][0]);
merge(ch[p][1], ch[q][1]);
siz[p] = siz[ch[p][0]] + siz[ch[p][1]];// 合并的一部分, 合并后q就不会再使用了, 所以只操作p就可以了
tail[p] = tail[q];//可以去掉这个赋值? 对于非叶子结点, tail都是0, 但对于叶子结点不清楚 >>>>>>>>>>>>>>>>>>>>>>>>>>
}
pii query(int u, int v, int w){
int ans = 0;
G(i, 30, 0){
int c = (w >> i) & 1;
if(ch[u][c] && siz[ch[u][c]] - siz[ch[v][c]] > 0) u = ch[u][c], v = ch[v][c];
else ans |= (1 << i), u = ch[u][c ^ 1], v = ch[v][c ^ 1];//v 的 移动本质上是 u 的同步, 所以都要 c ^ 1
}
return make_pair(tail[u], ans);//最后选中了哪个点, 代价是多少
}
ll boruvka(){
F(i, 1, n) fa[i] = i;
int pd = 1;
ll sum = 0;
while(pd){
pd = 0;
F(i, 1, n) val[i] = inf, best[i] = 0;
F(i, 1, n){
int x = get(i);
pii ret = query(root[0], root[x], a[i]);//找和a[i]异或得到的结果最小的点
int y = get(ret.fi), w = ret.se;
//注意y要找祖先!
if(x != y){//不在同一集合才能连
if(w < val[x]) best[x] = y, val[x] = w;
if(w < val[y]) best[y] = x, val[y] = w;
}
}
F(i, 1, n){
if(val[i] < inf && get(i) != get(best[i])){
//不用判 best[i]!=0, 因为如果=0, 那val[i]必然=inf, 这也是为什么best可以不清空的原因
sum += val[i];
pd = 1;
merge(root[get(i)], root[get(best[i])]);
fa[get(best[i])] = get(i);
}
}
}
return sum;
}
signed main(){
// freopen("test.in","r",stdin);
// freopen("test.out","w",stdout);
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> n; F(i, 1, n) cin >> a[i];
sort(a + 1, a + 1 + n);
n = unique(a + 1, a + 1 + n) - a - 1;//要去重, 相同权值的点连边其实可以全部等效在一个点上, 而且不去重算出来的siz会加倍, 问题就多了
F(i, 1, n)insert(root[0], i, a[i]), insert(root[i], i, a[i]);
cout << boruvka() << '\n';
return 0;
}
题解:CF888G Xor-MST的更多相关文章
- [题解] [AtCoder2134] Zigzag MST
题面 题解 考虑kruscal的过程 对于三个点\(x, y, x + 1\), 我们可以将\((x, y, z), (y, x + 1, z + 1)\)看做\((x, y, z), (x, x + ...
- 题解-CF617E XOR and Favorite Number
题面 CF617E XOR and Favorite Number 给定 \(n,m,k\) 和 \(n\) 个数的序列 \(a_i\),\(m\) 次求区间 \([l,r]\) 中异或值为 \(k\ ...
- 题解 [AT2134] Zigzag MST
题面 解析 我们先考虑一下加一条边(x,y,z)会成什么亚子: (还有很多边不画了...) 然后我们把这个图单独拿出来: 我们可以发现,对于最小生成树的贡献, 它是等价于下面这张图的(因为连通性一样) ...
- CodeForces 979 D Kuro and GCD and XOR and SUM
Kuro and GCD and XOR and SUM 题意:给你一个空数组. 然后有2个操作, 1是往这个数组里面插入某个值, 2.给你一个x, k, s.要求在数组中找到一个v,使得k|gcd( ...
- BZOJ3390: [Usaco2004 Dec]Bad Cowtractors牛的报复
3390: [Usaco2004 Dec]Bad Cowtractors牛的报复 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 43 Solved: ...
- [Luogu 3690]【模板】Link Cut Tree (动态树)
Description 给定N个点以及每个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和. ...
- bzoj 1954 & poj 3764 The xor-longest Path dfs+Trie
题目大意 给定一棵n个点的带权树,求树上最长的异或和路径 题解 因为\(xor\)操作满足可结合性,所以有 \(a\text{ }xor\text{ }b\text{ }xor\text{ }b = ...
- NOIP模拟 17.9.28
公交车[问题描述]市内有
- 题解-AtCoder Code-Festival2017 Final-J Tree MST
Problem \(\mathrm{Code~Festival~2017~Final~J}\) 题意概要:一棵 \(n\) 个节点有点权边权的树.构建一张完全图,对于任意一对点 \((x,y)\),连 ...
- BZOJ2337:[HNOI2011]XOR和路径——题解
+++++++++++++++++++++++++++++++++++++++++++ +本文作者:luyouqi233. + +欢迎访问我的博客:http://www.cnblogs.com/luy ...
随机推荐
- 关于Vue + element plus包装Component理解
关于Vue + element plus包装Component理解 一.关于编写思路 我以设计el-select选择框进行举例说明 父组件与Component传递params与Function使用Pr ...
- SMU Spring 2023 Contest Round 2(待补
M. Different Billing #include <map> #include <set> #include <cmath> #include <q ...
- STM32F3, STM32F4编程手册
1. Cortex-M4的内核设备 NVIC, Nested vectored interrupt controller SCB, System control block SysTick, The ...
- bazel简介(二)——从makefile向bazel转变(使用genrule)
0x01 背景 上篇中已经介绍了bazel的基本工作原理和相关的概念.这篇将继续介绍下,现有的makefile构建工程如何切换到bazel构建系统. bazel提供了丰富的扩展方式,当然也支持从目前的 ...
- 阿里云图床(PicGo+阿里云OSS)搭建
阿里云图床搭建方法: 1.登录阿里云,搜索对象存储oss,新用户免费使用3个月20G,到期后,一年也就9元左右,还是很划算的. 2.在左侧列表里,点击Bucket列表,创建Bucket 3.Bucke ...
- canvas实现图片标记
前言 由于业务需求,需要有一个图片标记功能,其实就是对图片画框画线做标记,类似微信的图片编辑 但是需要存下标记图及其标记的具体数据,.功能其实很简单,但刚开始的时候也是费了一些功夫的.我将原项目中该功 ...
- 总结:redis 突然变慢
用户量暴增,无法下单,凌晨的夜,静悄悄... 经过查找发现Redis. 获取不到连接资源,并且集群中的单台 Redis 连接量很高. 大量的流量没了 Redis 的缓存响应,直接打到了 MySQL,最 ...
- mysql 存储结构介绍及执行过程分析
MySQL体系结构介绍 1 mysql 的体系结构 MySQL整体的逻辑结构可以分为4层,客户层.服务层.存储引擎层.数据层 客户层 客户层:进行相关的连接处理.权限控制.安全处理等操作 服务层 服务 ...
- 使用 nuxi prepare 命令准备 Nuxt 项目
title: 使用 nuxi prepare 命令准备 Nuxt 项目 date: 2024/9/7 updated: 2024/9/7 author: cmdragon excerpt: 摘要:本文 ...
- 合合信息扫描全能王亮相静安区3·15活动,AI扫描带来绿色消费新体验
保护消费者的合法权益,是全社会的共同责任.为优化消费环境.促进品质消费高地建设,打造安全优质和谐的消费环境,上海静安区消保委于3月15日举办静安区2024年"3·15"国际消费者权 ...