【Foreign】远行 [LCT]
远行
Time Limit: 20 Sec Memory Limit: 256 MB
Description

Input

Output

Sample Input
0
5 10
1 4 5
2 3
2 5
2 1
1 5 3
1 1 4
2 3
2 5
1 5 2
2 1
Sample Output
0
1
0
3
2
3
HINT

Main idea
每次连上一条边,询问一个点和其能到达最远的点的距离。
Solution
由于每次要脸上一条边,我们显然使用LCT,然后一个点到达的最远的点必然是树的直径上的端点,我们合并两棵树维护直径的时候,暴力分几种情况讨论一下即可。
Code
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
using namespace std;
typedef long long s64; const int ONE = ;
const int MOD = 1e9+; int Type,n,Q;
int opt,x,y;
int fat[ONE];
int Ans; int get()
{
int res=,Q=; char c;
while( (c=getchar())< || c>)
if(c=='-')Q=-;
if(Q) res=c-;
while((c=getchar())>= && c<=)
res=res*+c-;
return res*Q;
} int Find(int x)
{
if(fat[x]==x) return x;
return fat[x]=Find(fat[x]);
} namespace LCT
{
int lc[ONE],rc[ONE],fa[ONE];
int hasRev[ONE];
int L[ONE],R[ONE],dis[ONE],size[ONE]; void pre()
{
for(int i=;i<=n;i++)
fat[i]=L[i]=R[i]=i,
size[i]=;
} void Update(int x)
{
size[x] = size[lc[x]] + size[rc[x]] + ;
} bool is_real(int x)
{
return (lc[fa[x]]==x || rc[fa[x]]==x);
} void tag_rev(int x)
{
hasRev[x]^=;
swap(lc[x],rc[x]);
} void tag_down(int x)
{
if(hasRev[x])
{
tag_rev(lc[x]);
tag_rev(rc[x]);
hasRev[x]=;
}
} void Turn(int x)
{
int y=fa[x],z=fa[y];
int b= x==lc[y]?rc[x]:lc[x]; fa[y]=x; fa[x]=z;
if(b) fa[b]=y; if(z)
{
if(y==lc[z]) lc[z]=x;
else if(y==rc[z]) rc[z]=x;
} if(x==lc[y]) rc[x]=y,lc[y]=b;
else lc[x]=y,rc[y]=b; Update(y); Update(x);
} void Splay(int x)
{
static int anc[ONE];
int anc_num=;
anc[++anc_num] = x;
for(int i=x; is_real(i); i=fa[i]) anc[++anc_num]=fa[i];
while(anc_num>) tag_down(anc[anc_num--]);
while(is_real(x))
{
if(is_real(fa[x]))
{
if( (lc[fa[x]]==x) == (lc[fa[fa[x]]]==fa[x]) ) Turn(fa[x]);
else Turn(x);
}
Turn(x);
}
} void access(int x)
{
for(int p=x,q=; p; q=p,p=fa[q])
{
Splay(p);
rc[p] = q;
Update(p);
}
} void make_root(int x)
{
access(x); Splay(x); tag_rev(x);
} int dist(int x,int y)
{
make_root(x); access(y); Splay(y); return size[y]-;
} void link(int x,int y)
{
int lx,rx,ly,ry;
int Fx=Find(x), Fy=Find(y);
fat[Fy] = Fx;
make_root(x); fa[x]=y;
lx = L[Fx]; rx = R[Fx]; ly = L[Fy]; ry = R[Fy]; if(dist(lx,rx) >= dis[Fx]) dis[Fx]=dist(lx,rx), L[Fx]=lx, R[Fx]=rx;
if(dist(ly,ry) >= dis[Fx]) dis[Fx]=dist(ly,ry), L[Fx]=ly, R[Fx]=ry; if(dist(lx,ly) >= dis[Fx]) dis[Fx]=dist(lx,ly), L[Fx]=lx, R[Fx]=ly;
if(dist(lx,ry) >= dis[Fx]) dis[Fx]=dist(lx,ry), L[Fx]=lx, R[Fx]=ry;
if(dist(rx,ly) >= dis[Fx]) dis[Fx]=dist(rx,ly), L[Fx]=rx, R[Fx]=ly;
if(dist(rx,ry) >= dis[Fx]) dis[Fx]=dist(rx,ry), L[Fx]=rx, R[Fx]=ry; } void Query(int x)
{
int Fx=Find(x);
Ans = max( dist(L[Fx],x),dist(R[Fx],x) );
printf("%d\n",Ans);
}
} int main()
{
Type=get();
n=get(); Q=get();
LCT::pre();
while(Q--)
{
opt = get();
if(opt == )
{
x=get(); y=get();
if(Type==) x^=Ans, y^=Ans;
LCT::link(x,y);
}
else
{
x=get();
if(Type==) x^=Ans;
LCT::Query(x);
}
} }
【Foreign】远行 [LCT]的更多相关文章
- [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维护子树的直径]
树的直径一定是原联通块4个里的组合 1.LCT,维护树的直径,这题就做完了 2.直接倍增,lca啥的求求距离,也可以吧- // powered by c++11 // by Isaunoya #inc ...
- 4.17 省选模拟赛 远行 LCT 启发式合并 倍增
容易写出nQ的暴力 由于数据是期望的时间 所以直接dfs可以跑的很快 可以拿到70分. 当然 可以进一步优化暴力 使用换根dp 然后可以将暴力优化到n^2. const int MAXN=300010 ...
- 2019.2.28&2019.3.1 考试
因为没A/改几道题,就一起写了 题目在LOJ上都能找到 2019.2.28 100+20+12 前两个小时一直在睡觉+想题也没思路,我太菜了 T1 洗衣服 分开处理出洗衣服和烘干的时间,然后一边正着排 ...
- 【题解】【雅礼集训 2017 Day5】远行 LOJ 6038 LCT
Prelude 快要THUWC了,练一练板子. 传送到LOJ:o(TヘTo) Solution 首先有一条定理. 到树中任意一点的最远点一定是直径的两个端点之一. 我也不会证反正大家都在用,似乎可以用 ...
- LOJ#6038. 「雅礼集训 2017 Day5」远行(LCT)
题面 传送门 题解 要不是因为数组版的\(LCT\)跑得实在太慢我至于去学指针版的么--而且指针版的完全看不懂啊-- 首先有两个结论 1.与一个点距离最大的点为任意一条直径的两个端点之一 2.两棵树之 ...
- 【loj6038】「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT
题目描述 给你 $n$ 个点,支持 $m$ 次操作,每次为以下两种:连一条边,保证连完后是一棵树/森林:询问一个点能到达的最远的点与该点的距离.强制在线. $n\le 3\times 10^5$ ,$ ...
- 【Foreign】染色 [LCT][线段树]
染色 Time Limit: 20 Sec Memory Limit: 256 MB Description Input Output Sample Input 13 0 1 0 2 1 11 1 ...
- loj6038「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT
题目传送门 https://loj.ac/problem/6038 题解 根据树的直径的两个性质: 距离树上一个点最远的点一定是任意一条直径的一个端点. 两个联通块的并的直径是各自的联通块的两条直径的 ...
随机推荐
- 获取单片机唯一id(stm32获取单片机唯一id)
stm32唯一id: 不同型号的stm32单片机,id不在同一地址上!具体地址可以通过用户手册中的Device electronic signature>Unique device ID reg ...
- Ruby中数组的&操作
最近在忙一个项目,好久没有写日志了,项目终于接近尾声,可以适当放松一下,所以记一下在这个项目中发现的有趣事情: 数组的 与 操作 一直以为两个数组A和B相与,谁前谁后都一样,不过这次在项目中突然想试一 ...
- [转载] python 解析xml 文件: SAX方式
环境 python:3.4.4 准备xml文件 首先新建一个xml文件,countries.xml.内容是在python官网上看到的. <?xml version="1.0" ...
- restFul介绍及其使用规范
什么是REST和RESTful API? REST:(英文:Representational State Transfer,简称REST)表征性状态转移,是一种软件架构风格. RESTful : RE ...
- Android Service 服务(三)—— bindService与remoteService
(转自:http://blog.csdn.net/ithomer/article/details/7366396) 一.bindService简介 bindService是绑定Service服务, ...
- C++结构体排序
在C++中,对结构体的排序方式比C语言丰富的多.在C语言中,我们主要是通过qsort进行排序操作(抛开手写排序算法不说). 在C++<algorithm>中,有一个十分强大的排序函数sor ...
- 【iOS开发】iOS对UIViewController生命周期和属性方法的解析
iOS对UIViewController生命周期和属性方法的解析 一.引言 作为MVC设计模式中的C,Controller一直扮演着项目开发中最重要的角色,它是视图和数据的桥梁,通过它的管理,将数据有 ...
- onkeypress,onkeyup,onkeydown区别
onkeypress 这个事件在用户按下并放开任何字母数字键时发生.系统按钮(例如,箭头键和功能键)无法得到识别. onkeyup 这个事件在用户放开任何先前按下的键盘键时发生. onkeydown ...
- PokeCats开发者日志(三)
现在是PokeCats游戏开发的第四天的晚上,明天要过周末了,所以提前写一下开发者日志吧! day4 day4主要是优化界面和增加游戏可玩性. (1)感觉只有三只喵喵的话,玩家只需要无脑点 ...
- ActiveMQ入门代码
Hello world程序演示: 生产者: package com.mq.helloworld; import javax.jms.Connection; import javax.jms.Conne ...