【loj6038】「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT
给你 $n$ 个点,支持 $m$ 次操作,每次为以下两种:连一条边,保证连完后是一棵树/森林;询问一个点能到达的最远的点与该点的距离。强制在线。
$n\le 3\times 10^5$ ,$m\le 5\times 10^5$ 。
题解
树的直径+并查集+LCT
与直径相关的结论1:与一个点距离最大的点为任意一条直径的两个端点之一。
与直径相关的结论2:两棵树之间连一条边,新树直径的两个端点一定为第一棵树直径的两个端点和第二棵树直径的两个端点这四者中之二。
于是问题就变简单了,用并查集维护每个连通块的直径即可。由于强制在线,所以必须用LCT维护树上距离。
时间复杂度 $O(LCT·n\log n)=O(能过)$
#include <cstdio>
#include <algorithm>
#define N 300010
using namespace std;
int f[N] , px[N] , py[N] , fa[N] , c[2][N] , si[N] , rev[N];
int find(int x)
{
return x == f[x] ? x : f[x] = find(f[x]);
}
inline void pushup(int x)
{
si[x] = si[c[0][x]] + si[c[1][x]] + 1;
}
inline void pushdown(int x)
{
if(rev[x])
{
swap(c[0][c[0][x]] , c[1][c[0][x]]) , rev[c[0][x]] ^= 1;
swap(c[0][c[1][x]] , c[1][c[1][x]]) , rev[c[1][x]] ^= 1;
rev[x] = 0;
}
}
inline bool isroot(int x)
{
return x != c[0][fa[x]] && x != c[1][fa[x]];
}
void update(int x)
{
if(!isroot(x)) update(fa[x]);
pushdown(x);
}
inline void rotate(int x)
{
int y = fa[x] , z = fa[y] , l = (c[1][y] == x) , r = l ^ 1;
if(!isroot(y)) c[c[1][z] == y][z] = x;
fa[x] = z , fa[y] = x , fa[c[r][x]] = y , c[l][y] = c[r][x] , c[r][x] = y;
pushup(y) , pushup(x);
}
inline void splay(int x)
{
int y , z;
update(x);
while(!isroot(x))
{
y = fa[x] , z = fa[y];
if(!isroot(y))
{
if((c[0][y] == x) ^ (c[0][z] == y)) rotate(x);
else rotate(y);
}
rotate(x);
}
}
inline void access(int x)
{
int t = 0;
while(x) splay(x) , c[1][x] = t , pushup(x) , t = x , x = fa[x];
}
inline void makeroot(int x)
{
access(x) , splay(x) , swap(c[0][x] , c[1][x]) , rev[x] ^= 1;
}
inline int dis(int x , int y)
{
makeroot(x) , access(y) , splay(y);
return si[y];
}
inline void link(int x , int y)
{
int tx = find(x) , ty = find(y) , mx = -1 , t , rx , ry;
makeroot(x) , fa[x] = y;
if(mx < (t = dis(px[tx] , py[tx]))) mx = t , rx = px[tx] , ry = py[tx];
if(mx < (t = dis(px[ty] , py[ty]))) mx = t , rx = px[ty] , ry = py[ty];
if(mx < (t = dis(px[tx] , px[ty]))) mx = t , rx = px[tx] , ry = px[ty];
if(mx < (t = dis(px[tx] , py[ty]))) mx = t , rx = px[tx] , ry = py[ty];
if(mx < (t = dis(py[tx] , px[ty]))) mx = t , rx = py[tx] , ry = px[ty];
if(mx < (t = dis(py[tx] , py[ty]))) mx = t , rx = py[tx] , ry = py[ty];
f[tx] = ty , px[ty] = rx , py[ty] = ry;
}
int main()
{
int type , n , q , i , opt , x , y , ans = 0;
scanf("%d%d%d" , &type , &n , &q);
for(i = 1 ; i <= n ; i ++ ) f[i] = px[i] = py[i] = i , si[i] = 1;
while(q -- )
{
scanf("%d%d" , &opt , &x) , x ^= ans;
if(opt == 1) scanf("%d" , &y) , y ^= ans , link(x , y);
else y = find(x) , printf("%d\n" , ans = max(dis(x , px[y]) , dis(x , py[y])) - 1);
if(!type) ans = 0;
}
return 0;
}
【loj6038】「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT的更多相关文章
- loj6038「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT
题目传送门 https://loj.ac/problem/6038 题解 根据树的直径的两个性质: 距离树上一个点最远的点一定是任意一条直径的一个端点. 两个联通块的并的直径是各自的联通块的两条直径的 ...
- [loj6038]「雅礼集训 2017 Day5」远行 lct+并查集
给你 n 个点,支持 m 次操作,每次为以下两种:连一条边,保证连完后是一棵树/森林:询问一个点能到达的最远的点与该点的距离.强制在线. n≤3×10^5 n≤3×10^5 ,m≤5×10^5 m≤5 ...
- LOJ#6038. 「雅礼集训 2017 Day5」远行(LCT)
题面 传送门 题解 要不是因为数组版的\(LCT\)跑得实在太慢我至于去学指针版的么--而且指针版的完全看不懂啊-- 首先有两个结论 1.与一个点距离最大的点为任意一条直径的两个端点之一 2.两棵树之 ...
- 【刷题】LOJ 6038 「雅礼集训 2017 Day5」远行
题目描述 Miranda 生活的城市有 \(N\) 个小镇,一开始小镇间没有任何道路连接.随着经济发现,小镇之间陆续建起了一些双向的道路但是由于经济不太发达,在建设过程中,会保证对于任意两个小镇,最多 ...
- 「雅礼集训 2017 Day5」远行
题目链接 问题分析 要求树上最远距离,很显然就想到了树的直径.关于树的直径,有下面几个结论: 如果一棵树的直径两个端点为\(a,b\),那么树上一个点\(v\)开始的最长路径是\(v\rightarr ...
- loj#6038 「雅礼集训 2017 Day5」远行
分析 代码 #include<bits/stdc++.h> using namespace std; #define fi first #define se second #define ...
- 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}$表 ...
随机推荐
- Luogu3804 【模板】后缀自动机
题面 题解 一个串的出现次数等于$endpos$的大小,也是$parent$树上节点的$size$大小, 构建出后缀自动机,按拓补序,模拟即可. 代码 #include<cstdio> # ...
- 2288: 【POJ Challenge】生日礼物
2288: [POJ Challenge]生日礼物 https://lydsy.com/JudgeOnline/problem.php?id=2288 分析: 贪心+堆+链表. 首先把序列变一下,把相 ...
- [flex 布局]——flex教程
简介:2009年,W3C提出了一种新的方案----Flex布局,可以简便.完整.响应式地实现各种页面布局.目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能. Flex布局是什 ...
- IIC通讯程序
IIC程序 IIC起始信号 void IIC_Start(void) { SDA_OUT();//sda设为输出 IIC_SDA=; IIC_SCL=; delay_us();//延时一段时间,具体时 ...
- Git生成多个ssh key
在实际的工作中, 有可能需要连接多个远程仓库, 例如我想连接私有仓库.GitLab官网.GitHub官网, 那么同一台电脑就要生成多个ssh key: ssh-keygen -t rsa -C &qu ...
- Phaser3让超级玛丽实现轻跳、高跳及加上对应的跳跃声音
mario jumper 在线测试地址:http://www.ifiero.com/uploads/phaserjs3/jumper/ 空格键:轻按:跳低 ,长按:跳高键盘:--> 向右 , ...
- python爬取淘宝华为手机
import re from selenium import webdriver from selenium.common.exceptions import TimeoutException fro ...
- Delphi 实现照片抽奖-原创
有单位年会要用照片抽奖,上网搜了几个都不满意,且居然还要收费.自己写一个算了.只是有一点不爽,Delphi 7 在 Windows 7 64位下有问题,不能双击 dpr 文件直接打开项目! 关于性能: ...
- 一个小时搭建一个全栈 Web 应用框架
把想法变为现实的能力是空想家与实干家的区别.不管你是在一家跨国公司工作,还是正在为自己的创业公司而努力,那些有能力将创意转化为真正产品的人,都具有宝贵的技能并拥有明显的实力.如果你能在不到一个小时的时 ...
- 为phpStorm 配置PHP_CodeSniffer自动检查代码
通过composer 安装PHP_CodeSniffer : squizlabs/PHP_CodeSniffer gihub地址 composer global require "squiz ...