题解: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的更多相关文章

  1. [题解] [AtCoder2134] Zigzag MST

    题面 题解 考虑kruscal的过程 对于三个点\(x, y, x + 1\), 我们可以将\((x, y, z), (y, x + 1, z + 1)\)看做\((x, y, z), (x, x + ...

  2. 题解-CF617E XOR and Favorite Number

    题面 CF617E XOR and Favorite Number 给定 \(n,m,k\) 和 \(n\) 个数的序列 \(a_i\),\(m\) 次求区间 \([l,r]\) 中异或值为 \(k\ ...

  3. 题解 [AT2134] Zigzag MST

    题面 解析 我们先考虑一下加一条边(x,y,z)会成什么亚子: (还有很多边不画了...) 然后我们把这个图单独拿出来: 我们可以发现,对于最小生成树的贡献, 它是等价于下面这张图的(因为连通性一样) ...

  4. 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( ...

  5. BZOJ3390: [Usaco2004 Dec]Bad Cowtractors牛的报复

    3390: [Usaco2004 Dec]Bad Cowtractors牛的报复 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 43  Solved:  ...

  6. [Luogu 3690]【模板】Link Cut Tree (动态树)

    Description 给定N个点以及每个点的权值,要你处理接下来的M个操作.操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和. ...

  7. bzoj 1954 & poj 3764 The xor-longest Path dfs+Trie

    题目大意 给定一棵n个点的带权树,求树上最长的异或和路径 题解 因为\(xor\)操作满足可结合性,所以有 \(a\text{ }xor\text{ }b\text{ }xor\text{ }b = ...

  8. NOIP模拟 17.9.28

    公交车[问题描述]市内有

  9. 题解-AtCoder Code-Festival2017 Final-J Tree MST

    Problem \(\mathrm{Code~Festival~2017~Final~J}\) 题意概要:一棵 \(n\) 个节点有点权边权的树.构建一张完全图,对于任意一对点 \((x,y)\),连 ...

  10. BZOJ2337:[HNOI2011]XOR和路径——题解

    +++++++++++++++++++++++++++++++++++++++++++ +本文作者:luyouqi233. + +欢迎访问我的博客:http://www.cnblogs.com/luy ...

随机推荐

  1. Codeforces 929 div3 D

    题目:D. Turtle Tenacity: Continual Mods 题目链接:https://codeforces.com/contest/1933/problem/D 算法:数论.贪心. 一 ...

  2. OpenHarmony编译构建系统详解,从零搭建windows下开发环境,巨方便!

    自从OpenHarmony更新了dev-tool,就可以在windows下构建鸿蒙(轻量型)系统了,这对于进行MCU开发的朋友们,学习鸿蒙OS会友好许多!我们可以更快的构建出系统,方便快速学习和验证. ...

  3. LLM应用实战: 产业治理多标签分类

    1. 背景 许久未见,甚是想念~ 近期本qiang~换了工作,处于新业务适应期,因此文章有一段时间未更新,理解万岁! 现在正在着手的工作是产业治理方面,主要负责其中一个功能模块,即按照产业治理标准体系 ...

  4. 关于腾讯会议pc端的使用教程

    一.首先先在官网下载pc端 下面是连接:腾讯会议_腾讯会议下载- 腾讯云 (tencent.com) 点击免费下载即可. 二.登录并创建会议 选择一种登录方式. 创建会议有快速会议和预定会议两种方式 ...

  5. 使用 Docker 部署 FRP

    服务端 编写配置文件 vim ~/.config/frp/frps.toml bindPort = 7000 # Web Dashboard [webServer] addr = "0.0. ...

  6. 使用Golang的协程竟然变慢了|100万个协程的归并排序耗时分析

    前言 这篇文章将用三个版本的归并排序,为大家分析使用协程排序的时间开销(被排序的切片长度由128到1000w) 本期demo地址:https://github.com/BaiZe1998/go-lea ...

  7. WebShell流量特征检测_中国菜刀篇

    80后用菜刀,90后用蚁剑,95后用冰蝎和哥斯拉,以phpshell连接为例,本文主要是对这四款经典的webshell管理工具进行流量分析和检测. 什么是一句话木马? 1.定义 顾名思义就是执行恶意指 ...

  8. MDC – Text field

    前言 Angular Material 只有 Form field, 但 Material Design 有份 Text field 和 Form field, Form field 是给 check ...

  9. Blazor静态服务端呈现(静态SSR)身份认证

    本文介绍 Blazor 静态服务端呈现(静态 SSR)模式下,用户登录身份认证是如何实现的. 1. SSR 简介 SSR 是服务器侧呈现,HTML 是由服务器上的 ASP.NET Core 运行时生成 ...

  10. 使用 Wake Lock API:保持设备唤醒的最佳实践

    在现代 Web 应用中,尤其是涉及视频播放.实时通信.地图导航等长时间运行的任务时,用户常常希望设备不要因为空闲而自动进入睡眠模式或屏幕变暗.为了解决这一问题,Web API 提供了一个名为 Wake ...