「雅礼集训 2017 Day5」远行
问题分析
要求树上最远距离,很显然就想到了树的直径。关于树的直径,有下面几个结论:
- 如果一棵树的直径两个端点为\(a,b\),那么树上一个点\(v\)开始的最长路径是\(v\rightarrow a\)或\(v \rightarrow b\)。
- 如果有两棵树,直径分别为\(a_1,b_1\)和\(a_2,b_2\),那么在这两棵树间连一条边,新树的直径只可能是\(a_1\rightarrow b_1,a_1\rightarrow a_2, a_1\rightarrow b_2, a_2\rightarrow a_1, a_2 \rightarrow b_1, a_2 \rightarrow b_2\)这\(6\)种可能。
那么这道题就是用并查集维护每棵树的直径的两端,然后用LCT维护树的形态即可。如果需要树的直径性质的证明,可以在下方留言。
参考程序
#include <bits/stdc++.h>
using namespace std;
const int Maxn = 300010;
int Father[ Maxn ], Child[ Maxn ][ 2 ], Stack[ Maxn ], Tag[ Maxn ];
int Size[ Maxn ];
int N, Q, Rec[ Maxn ][ 2 ], Fa[ Maxn ], Type;
void Collect( int Ind ) {
Size[ Ind ] = Size[ Child[ Ind ][ 0 ] ] + Size[ Child[ Ind ][ 1 ] ] + 1;
return;
}
void TagOn( int Ind ) {
Tag[ Ind ] ^= 1;
swap( Child[ Ind ][ 0 ], Child[ Ind ][ 1 ] );
return;
}
void TagDown( int Ind ) {
if( Tag[ Ind ] ) {
TagOn( Child[ Ind ][ 0 ] );
TagOn( Child[ Ind ][ 1 ] );
Tag[ Ind ] ^= 1;
}
return;
}
bool IsRoot( int Ind ) {
if( Ind == 0 ) return true;
return !( ( Child[ Father[ Ind ] ][ 0 ] == Ind ) || ( Child[ Father[ Ind ] ][ 1 ] == Ind ) );
}
void Rotate( int C ) {
int B = Father[ C ];
int A = Father[ B ];
int Tag = Child[ B ][ 1 ] == C;
if( !IsRoot( B ) ) Child[ A ][ Child[ A ][ 1 ] == B ] = C;
Father[ C ] = A;
Child[ B ][ Tag ] = Child[ C ][ Tag ^ 1 ];
Father[ Child[ C ][ Tag ^ 1 ] ] = B;
Child[ C ][ Tag ^ 1 ] = B;
Father[ B ] = C;
Collect( B ); Collect( C );
return;
}
void Splay( int Ind ) {
if( Ind == 0 ) return;
int Num = 0; Stack[ ++Num ] = Ind; int Temp = Ind;
while( !IsRoot( Temp ) ) {
Temp = Father[ Temp ];
Stack[ ++Num ] = Temp;
}
for( int i = Num; i >= 1; --i ) TagDown( Stack[ i ] );
while( !IsRoot( Ind ) ) {
int X = Father[ Ind ];
int Y = Father[ X ];
if( !IsRoot( X ) )
if( ( Child[ Y ][ 0 ] == X ) ^ ( Child[ X ][ 0 ] == Ind ) )
Rotate( Ind );
else
Rotate( X );
Rotate( Ind );
}
Collect( Ind );
return;
}
void Access( int Ind ) {
for( int i = 0; Ind; i = Ind, Ind = Father[ Ind ] ) {
Splay( Ind ); Child[ Ind ][ 1 ] = i; Collect( Ind );
}
return;
}
void MakeRoot( int Ind ) {
Access( Ind );
Splay( Ind );
TagOn( Ind );
return;
}
int FindRoot( int Ind ) {
Access( Ind ); Splay( Ind );TagDown( Ind );
while( Child[ Ind ][ 0 ] ) {
Ind = Child[ Ind ][ 0 ]; TagDown( Ind );
}
Splay( Ind );
return Ind;
}
void Split( int x, int y ) {
MakeRoot( x );
Access( y );
Splay( y );
return;
}
void Link( int x, int y ) {
MakeRoot( x );
if( FindRoot( y ) == x ) return;
Father[ x ] = y;
return;
}
void Cut( int x, int y ) {
MakeRoot( x );
if( FindRoot( y ) != x || Child[ y ][ 0 ] || Father[ y ] != x ) return;
Father[ y ] = Child[ x ][ 1 ] = 0;
Collect( x );
return;
}
int GetFather( int x ) {
if( Fa[ x ] == x ) return x;
Fa[ x ] = GetFather( Fa[ x ] );
return Fa[ x ];
}
int main() {
scanf( "%d", &Type );
scanf( "%d%d", &N, &Q );
for( int i = 1; i <= N; ++i ) {
Fa[ i ] = i;
Size[ i ] = 1;
Rec[ i ][ 0 ] = Rec[ i ][ 1 ] = i;
}
int LastAns = 0;
for( int i = 1; i <= Q; ++i ) {
int Opt; scanf( "%d", &Opt );
if( Opt == 1 ) {
int u, v; scanf( "%d%d", &u, &v );
if( Type ) u ^= LastAns, v ^= LastAns;
int U = GetFather( u ), V = GetFather( v );
if( U == V ) continue;
int Max = 0, x, y;
Split( Rec[ U ][ 0 ], Rec[ U ][ 1 ] );
if( Size[ Rec[ U ][ 1 ] ] > Max ) {
Max = Size[ Rec[ U ][ 1 ] ];
x = Rec[ U ][ 0 ]; y = Rec[ U ][ 1 ];
}
Split( Rec[ V ][ 0 ], Rec[ V ][ 1 ] );
if( Size[ Rec[ V ][ 1 ] ] > Max ) {
Max = Size[ Rec[ V ][ 1 ] ];
x = Rec[ V ][ 0 ]; y = Rec[ V ][ 1 ];
}
Link( u, v ); Fa[ U ] = V;
for( int j = 0; j < 2; ++j )
for( int k = 0; k < 2; ++k ) {
Split( Rec[ U ][ j ], Rec[ V ][ k ] );
if( Size[ Rec[ V ][ k ] ] > Max ) {
Max = Size[ Rec[ V ][ k ] ];
x = Rec[ U ][ j ]; y = Rec[ V ][ k ];
}
}
Rec[ V ][ 0 ] = x; Rec[ V ][ 1 ] = y;
} else {
int u; scanf( "%d", &u );
if( Type ) u ^= LastAns;
int U = GetFather( u );
LastAns = 0;
for( int j = 0; j < 2; ++j ) {
Split( Rec[ U ][ j ], u );
LastAns = max( LastAns, Size[ u ] );
}
--LastAns;
printf( "%d\n", LastAns );
fflush( stdout );
}
}
return 0;
}
「雅礼集训 2017 Day5」远行的更多相关文章
- LOJ#6038. 「雅礼集训 2017 Day5」远行(LCT)
题面 传送门 题解 要不是因为数组版的\(LCT\)跑得实在太慢我至于去学指针版的么--而且指针版的完全看不懂啊-- 首先有两个结论 1.与一个点距离最大的点为任意一条直径的两个端点之一 2.两棵树之 ...
- 【loj6038】「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT
题目描述 给你 $n$ 个点,支持 $m$ 次操作,每次为以下两种:连一条边,保证连完后是一棵树/森林:询问一个点能到达的最远的点与该点的距离.强制在线. $n\le 3\times 10^5$ ,$ ...
- 【刷题】LOJ 6038 「雅礼集训 2017 Day5」远行
题目描述 Miranda 生活的城市有 \(N\) 个小镇,一开始小镇间没有任何道路连接.随着经济发现,小镇之间陆续建起了一些双向的道路但是由于经济不太发达,在建设过程中,会保证对于任意两个小镇,最多 ...
- [loj6038]「雅礼集训 2017 Day5」远行 lct+并查集
给你 n 个点,支持 m 次操作,每次为以下两种:连一条边,保证连完后是一棵树/森林:询问一个点能到达的最远的点与该点的距离.强制在线. n≤3×10^5 n≤3×10^5 ,m≤5×10^5 m≤5 ...
- loj#6038 「雅礼集训 2017 Day5」远行
分析 代码 #include<bits/stdc++.h> using namespace std; #define fi first #define se second #define ...
- loj6038「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT
题目传送门 https://loj.ac/problem/6038 题解 根据树的直径的两个性质: 距离树上一个点最远的点一定是任意一条直径的一个端点. 两个联通块的并的直径是各自的联通块的两条直径的 ...
- LOJ#6038. 「雅礼集训 2017 Day5」远行 [LCT维护子树的直径]
树的直径一定是原联通块4个里的组合 1.LCT,维护树的直径,这题就做完了 2.直接倍增,lca啥的求求距离,也可以吧- // powered by c++11 // by Isaunoya #inc ...
- 「雅礼集训 2017 Day5」珠宝
题目描述 Miranda 准备去市里最有名的珠宝展览会,展览会有可以购买珠宝,但可惜的是只能现金支付,Miranda 十分纠结究竟要带多少的现金,假如现金带多了,就会比较危险,假如带少了,看到想买的右 ...
- 「雅礼集训 2017 Day5」矩阵
填坑填坑.. 感谢wwt耐心讲解啊.. 如果要看这篇题解建议从上往下读不要跳哦.. 30pts 把$A$和$C$看成$n$个$n$维向量,那$A_i$是否加入到$C_j$中就可以用$B_{i,j}$表 ...
随机推荐
- ps -ef
status, msg = commands.getstatusoutput("ps -ef | grep start.sh | grep -Fv grep | awk '{print $1 ...
- 客户端相关知识学习(一)之混合开发,为什么要在App中使用H5页面以及应用场景、注意事项
混合开发 随着移动互联网的高速发展,常规的开发速度已经渐渐不能满足市场需求.原生H5混合开发应运而生,目前,市场上许多主流应用都有用到混合开发,例如支付宝.美团等.下面,结合我本人的开发经验,简单谈一 ...
- LOJ题解#136. 最小瓶颈路 DFS+Kruskal
题目链接: https://loj.ac/problem/136 思路: 在我的这篇博客中已经讲到什么是最短瓶颈路,同时给出了一个用Kruskal求最短瓶颈路的一个简洁易懂的方法,然而这道题目可以看作 ...
- git简易操作手册
从远程仓库新建 $ git clone https://github.com/xxxr/Repository.git $ cd Repository/ $ git config --global us ...
- Spring的基本应用(1):IDEA版本
一.Spring概述: 1.什么是Spring? Spring是分层的JavaSE/EE应用full-stack(一站式)轻量级开源框架,以IoC(Inverse Of Control:控制反转)和A ...
- LVS Director端服务启动脚本
#!/bin/bash # 手动安装lpvs前端管理工具 # chkconfig: - # # lvs启动脚本:director # lvs模式类型:nat.dr.ipip # lvs代理协议:tcp ...
- 3.(基础)tornado的接口调用顺序与模板
上一节介绍了tornado的请求与响应,这一节介绍tornado的接口调用顺序和模板 首先都有哪些接口呢?作用是什么呢?并且都有的时候,执行顺序是怎么样的呢? 接口 1.initialize,表示初始 ...
- django用户投票系统详解
投票系统之详解 1.创建项目(mysite)与应用(polls) django-admin.py startproject mysite python manage.py startapp polls ...
- Elasticsearch改动
随着Elasticsearch的版本升级,Elasticsearch的一些特性也在改变,下面是一些需要注意的地方 v6.x 版本之前 : 一个index下面是可以创建多个type v6.x 版本 : ...
- 换个眼界看IE,它真的有那么可恶吗?
一说到IE我想很多web小伙伴都避之不及,对于IE经验不足的同学可以说更是恨之入骨,撕心裂肺般的烦恼与气愤?,被折磨的不要不要的.我感同身受,去年的我的生日愿望就是,我希望IE浏览器在这世界上没有一个 ...