[luogu-P4299] 首都(并查集 + LCT动态维护树的重心 / 维护虚儿子信息)

problem

luogu-P4299

solution

本题考察了很经典的模型,运用了很经典的解法。

本题用到了重心的两个性质:

  • 两棵树合并为同一棵树时,新的重心一定在原来两棵树各自重心的路径上。

  • 重心为根时的最大子树大小最小,不超过 siz/2siz/2siz/2

    如果树节点个数为奇数,则只有一个重心。否则有两个重心。

找到 x,yx,yx,y 各自所在的国家的重心 gx,gygx,gygx,gy

x,yx,yx,y 连边完成国家合并。

然后把 gx−gygx-gygxgy 的路径 split\text{split}split 出来。

接着就暴力 dfs\text{dfs}dfs 根据左右儿子的 siz\text{siz}siz 判断走左还是走右,因为每次 sizsizsiz 至少减小一半,所以时间复杂度仍然是一个 logloglog

具体而言:当左右子树 siz\text{siz}siz 都不超过总个数的一半时,将这个点纳入重心备选。然后看左右儿子谁的 sizsizsiz 更大,就往哪边走。

但是很遗憾 LCT\text{LCT}LCT 认父不认子,对于一个点只能记录两个左右儿子的 siz\text{siz}siz

我们好像不能获得一个点的子树内所有的节点个数?

这就是一个 LCT\text{LCT}LCT 经典应用了。

t[i].sizt[i].sizt[i].siz 记录 iii 子树大小,t[i].tott[i].tott[i].tot 记录除开两个左右儿子的 sizsizsiz,其余虚儿子的 sizsizsiz 的和。

更新就需要写成:

t[x].siz = t[t[x].son[0]].siz + t[t[x].son[1]].siz + 1 + t[x].tot;

与此同时,所有涉及更改虚实儿子的,都要重新维护 tottottot

一般就是 access\text{access}access 中的操作,会多加一行。

t[x].tot += t[t[x].son[1]].siz - t[son].siz;

而且为了保证信息的时效性,我们的 link\text{link}link 操作要还是像以前一样,直接记一下 xxx 的父亲是 yyy 就不行了。

也不能直接把 yyy 的信息更新一下就完了。

因为一旦 x,yx,yx,y 连边,各自所在的子树的位置一路往上信息都要修改。

所以我们不如直接让 x,yx,yx,y 成为联通块的根,split(x,y)\text{split(x,y)}split(x,y) 即可。

由于 LCTLCTLCTfindroot\text{findroot}findroot 慢得慌,我们直接用并查集维护每个联通块的重心即可,重心的异或和也用个变量维护即可。

具体可见代码实现。

code

#include <bits/stdc++.h>
using namespace std;
#define maxn 100005namespace LCT {int top = 0, sta[maxn];struct node { int son[2], fa, tot, tag, siz; }t[maxn];bool root( int x ) { return t[t[x].fa].son[0] ^ x and t[t[x].fa].son[1] ^ x; }void pushup( int x ) { t[x].siz = t[t[x].son[0]].siz + t[t[x].son[1]].siz + 1 + t[x].tot; }void reverse( int x ) { swap( t[x].son[0], t[x].son[1] ); t[x].tag ^= 1; }void pushdown( int x ) {if( ! t[x].tag ) return;if( t[x].son[0] ) reverse( t[x].son[0] );if( t[x].son[1] ) reverse( t[x].son[1] );t[x].tag = 0;}void rotate( int x ) {int fa = t[x].fa;int Gfa = t[fa].fa;int d = t[fa].son[1] == x;if( ! root( fa ) ) t[Gfa].son[t[Gfa].son[1] == fa] = x;t[x].fa = Gfa;if( t[x].son[d ^ 1] ) t[t[x].son[d ^ 1]].fa = fa;t[fa].son[d] = t[x].son[d ^ 1];t[x].son[d ^ 1] = fa;t[fa].fa = x;pushup( fa );pushup( x );}void splay( int x ) {sta[++ top] = x; int y = x;while( ! root( y ) ) sta[++ top] = y = t[y].fa;while( top ) pushdown( sta[top --] );while( ! root( x ) ) {int fa = t[x].fa, Gfa = t[fa].fa;if( ! root( fa ) ) (t[Gfa].son[1] == fa) ^ (t[fa].son[1] == x) ? rotate( x ) : rotate( fa );rotate( x ); }}void access( int x ) { for( int son = 0;x;son = x, x = t[x].fa ) { splay( x );t[x].tot += t[t[x].son[1]].siz - t[son].siz;t[x].son[1] = son;pushup( x ); }}void makeroot( int x ) { access( x ); splay( x ); reverse( x ); }void split( int x, int y ) { makeroot( x ); access( y ); splay( y ); }void link( int x, int y ) { split( x, y ); t[t[x].fa = y].tot += t[x].siz; pushup( y ); }int dfs( int x ) {int lsum = 0, rsum = 0, siz = t[x].siz >> 1, flag = t[x].siz & 1, ans = 1e9;while( x ) {pushdown( x );int lcnt = lsum + t[t[x].son[0]].siz;int rcnt = rsum + t[t[x].son[1]].siz;if( lcnt <= siz and rcnt <= siz ) {if( flag ) { ans = x; break; }else ans = min( ans, x );}if( lcnt < rcnt ) { lsum += t[x].siz - t[t[x].son[1]].siz; // + t[t[x].son[0]].siz + t[x].tot + 1x = t[x].son[1];}else {rsum += t[x].siz - t[t[x].son[0]].siz; // +t[t[x].son[1]].siz + t[x].tot + 1x = t[x].son[0];}}splay( ans );return ans;}
}int f[maxn];
int find( int x ) { return x == f[x] ? x : f[x] = find( f[x] ); }int main() {int ans = 0, x, y, n, m; char opt[10];scanf( "%d %d", &n, &m );iota( f + 1, f + n + 1, 1 );for( int i = 1;i <= n;i ++ ) ans ^= i;for( int i = 1;i <= m;i ++ ) {scanf( "%s", opt );switch( opt[0] ) {case 'X' : printf( "%d\n", ans ); break;case 'Q' : {scanf( "%d", &x );printf( "%d\n", find( x ) );break;}case 'A' : {scanf( "%d %d", &x, &y );LCT :: link( x, y );x = find( x ), y = find( y );LCT :: split( x, y );int g = LCT :: dfs( y );ans ^= x ^ y ^ g;f[x] = f[y] = f[g] = g;break;}}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316417.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算几何模板中的代码

计算几何模板代码选自kuangbin 7 计算几何 7.1 二维几何 // 计算几何模板 const double eps 1e-8; const double inf 1e20; const double pi acos(-1.0); const int maxp 1010; //Compares a double to zero int sgn(double x){if(fabs(x) < eps)return 0;if(x < …

机器学习 ML.NET 发布 1.0 RC

ML.NET 是面向.NET开发人员的开源和跨平台机器学习框架&#xff08;Windows&#xff0c;Linux&#xff0c;macOS&#xff09;,通过使用ML.NET,.NET开发人员可以利用他们现有的工具和技能组&#xff0c;为情感分析&#xff0c;推荐&#xff0c;图像分类等常见场景创建自定义机器…

[PA2015]Siano(线段树 + 二分)

problem luogu-P5579 solution 此题关键在于发现一个结论&#xff1a;生长速度快的草在任何时刻都不可能矮于生长速度慢的草。 正确性显然。 所以当我们将草按照 aaa 升序排序后&#xff0c;每次收割的草一定是一个后缀。 那么这个后缀的起点就可以二分找到。 割完后要对…

容器化时代我们应当选择Kubernetes

昨天发的文章《基于Kubernetes 构建.NET Core 的技术体系》&#xff0c;有同学问.NET Core上有Spring Cloud类似的平台吗&#xff1f; .NET Core出现这么久了&#xff0c;这个为云原生应用开发而准备的系统需要Spring cloud这样的全家桶吗&#xff1f; 大家希望使用Spring Clou…

2021杭电第8场

2021杭电第8场 题号题目知识点HDU 7056X-liked CountingHDU 7057Buying SnacksHDU 7058Ink on paperHDU 7059Counting StarsHDU 7060Separated NumberHDU 7061GCD GameHDU 7062A Simple ProblemHDU 7063Square CardHDU 7064Singing SuperstarHDU 7065Yinyang

[ZJOI2015]幻想乡 Wi-Fi 搭建计划(dp + 结论)

problem luogu-P3344 solution 这个题面&#xff0c;这个数据范围&#xff0c;完完全全就是网络流宗教。。然而我发现建不出来。 很多一眼网络流最后却不是网络流而往往是 dpdpdp 的题目都有一个特性&#xff1a;一个点可以流出多条流量&#xff0c;流入流量却只能为 111。…

CefSharp中c#和JavaScript交互读取电脑信息

介绍CEF是由Marshall Greenblatt于2008年创建的基于Google Chromium的BSD许可开源项目。与主要关注谷歌Chrome应用程序开发的Chromium项目本身不同&#xff0c;CEF专注于在第三方应用程序中促进嵌入式浏览器用例。CEF通过提供生产质量稳定的API&#xff0c;发布跟踪特定Chromiu…

Ink on paper HDU - 7058

Ink on paper HDU - 7058 题意&#xff1a; 给出n个墨水的初始位置&#xff0c;每秒向外扩展0.5cm&#xff0c;显示一个圆圈&#xff0c;问所有墨水连接起来需要多长时间 题解&#xff1a; 很明显&#xff0c;在完全图中找最小生成树&#xff0c;并记录最小生成树中最长的边…

加与乘(博弈论)

problem A,BA,BA,B 在玩游戏&#xff0c;给定一排长度为 nnn 的数列&#xff0c;每个人轮流取出任意一对相邻的两个数&#xff0c;然后把两个数的和或者乘积放入。 TTT 组询问。每组给定 n,mn,mn,m&#xff0c;接下来给定长度为 nnn 的数列 aia_iai​。 m0m0m0 AAA 先操作&…

C#8.0可空引用类型的使用注意要点

最近VS2019正式版发布了&#xff0c;装下来顺便试用了一下C#8.0&#xff0c;最大的看点应该就是可空引用类型了。不过C#8.0仍然处于Beta的状态&#xff0c;而且试用时也遇到了几个坑。背景知识说明&#xff1a;所谓的可空引用类型是指&#xff0c;一旦启用了可空引用类型这个新…

Singing Superstar HDU - 7064

Singing Superstar HDU - 7064 题意&#xff1a; 问在串T中出现了几次不相交的串S&#xff1f; 每次有n个串S询问 题解&#xff1a; AC自动机板子题。。 直接上模板 代码&#xff1a; #include <bits/stdc.h> #include <unordered_map> #define debug(a, b) …

ASP.NET Core Web 项目文件介绍

ASP.NET Core Web 项目文件在本视频中&#xff0c;我们将探索并了解asp.net core项目文件。 我们使用C&#xff03;作为编程语言&#xff0c;因此项目文件具有.csproj扩展名。如果您使用过以前版本的ASP.NET&#xff0c;那么您可能对此文件非常熟悉&#xff0c;但此文件中包含的…

[ZJOI2016] 小星星(树型dp + 状压dp + 容斥)

problem luogu-P3349 solution 这个数据首先就能想到状压 dpdpdp。 先考虑在树上的朴素 dp(i,j,S):dp(i,j,S):dp(i,j,S): 节点 iii 的对应原图编号为 jjj&#xff0c;其子树对应的编号构成的点集为 SSS 的方案数。 需要满足两个限制条件&#xff1a; 原图的每个节点只能被…

GCD Game HDU - 7061

GCD Game HDU - 7061 题意&#xff1a; 有n个数ai&#xff0c;两个人轮流操作&#xff0c;每次选择一个数ai&#xff0c;再人选一个x(1<x<ai)&#xff0c;然后用gcd(ai,x)代替ai 谁先不能操作谁先输掉比赛 题解&#xff1a; 第一反应nim游戏&#xff0c;gcd是取最大公…

[ZJOI2016]旅行者(网格图分治最短路)

problem luogu-P3350 solution 据说&#xff0c;网格图最短路用分治是一个人人皆知的套路。对不起我不是人 类比整体二分的算法流程。 考虑在一个 (xl,yl)−(yl,yr)(xl,yl)-(yl,yr)(xl,yl)−(yl,yr) 矩阵内处理 [ql,qr][ql,qr][ql,qr] 的询问。 以矩阵的中界线 mid\text{…

DotNetCore 3.0 助力 WPF 开发

前言Visual Studio 2019 已经正式发布了&#xff0c;DotNetCore 3.0 的正式版也指日可待。在之前的版本中&#xff0c;作为一名基于微软生态的传统 WPF 程序员看着隔壁同学在开发 DotNetCore 网站时用着各种特性好生羡慕&#xff0c;想着巨硬啥时候能让客户端开发者也能尝尝甜头…

H - Square Card HDU - 7063

H - Square Card HDU - 7063 题意&#xff1a; 有两个圆形区域&#xff0c;一个是得分区域&#xff0c;一个是获得奖金区域&#xff0c;现在你有一个边长为a的正方形,当正方形在如果在某一时刻它严格在圆形范围内&#xff0c;才算合法。 问把牌扔到任意的位置被得分和同时获得…

【刷题记录】排列dp

文章目录[AtCoder-ABC209-f] Deforestation[AtCoder-Educational DP Contest-T]Permutation「JOI Open 2016」摩天大楼topcoder srm 489 div1 lev3 : AppleTrees[CodeForces-626F] Group Projects[TopCoder] Seatfriends小结[AtCoder-ABC209-f] Deforestation 考虑相邻的两棵树…

《从零开始学ASP.NET CORE MVC》:VS2019创建ASP.NET Core Web程序(三)

创建ASP.NET Core Web应用程序如果您使用的是VS2017请看 VS2017创建ASP.NET Core Web程序(三)在这个视频中我们将讨论可用的不同项目模板及其功能预制的项目模板有什么不同&#xff0c;哪些是可以使用的&#xff0c;以及他们的作用。在Visual Studio 2019中创建新的ASP.NET Cor…

ASP.NET Core 沉思录 - 结构化日志

在 《ASP.NET Core 沉思录 - Logging 的两种介入方法》中我们介绍了 ASP.NET Core 中日志的基本设计结构。这一次我们来观察日志记录的格式&#xff0c;并进一步考虑如何在应用程序中根据不同的需求选择不同的日志记录形式。太长不读&#xff1a;直接飞到文章最后 :-DMicrosoft…