【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 题解 根据树的直径的两个性质: 距离树上一个点最远的点一定是任意一条直径的一个端点. 两个联通块的并的直径是各自的联通块的两条直径的 ...
随机推荐
- elasticsearch-mathc和term的区分
elasticsearch和mysql在思想上是有不同的,elasticsearch有分词一说,比如北京奥运分词成北京,奥运,北京奥运.分词要要考虑两点,一个是查询字符串要不要分词,还有就是原存储字段 ...
- 台湾ML笔记--1.2 formalize the learning probelm
Basic notations input: x∈χ (customer application) output: y∈y (good/bad after approving cred ...
- Android应用开发中的夜间模式实现(一)
前言 在应用开发中会经常遇到要求实现夜间模式或者主题切换具体例子如下,我会先讲解第一种方法. 夜间模式 知乎 网易新闻 沪江开心词场 Pocket 主题切换 腾讯QQ 新浪微博 我今天主要是详述第一种 ...
- 【个人训练】(POJ1837)Balance
这几天抓住国庆的黄金时间(因为没有女朋友,天天刷题emmmm 其实还在肝少前还要捞秋刀鱼) ,重点攻克掉几个基本的地方:搜索.dp.图论.这几天的题目应该就是这些范围. 题意 原题的意思大概是这样的, ...
- HDFS分布式集群
一.HDFS伪分布式环境搭建 Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统.它和现有的分布式文件系统有很多共同点.但同时, ...
- [leetcode-636-Exclusive Time of Functions]
Given the running logs of n functions that are executed in a nonpreemptive single threaded CPU, find ...
- [leetcode-634-Find the Derangement of An Array]
In combinatorial mathematics, a derangement is a permutation of the elements of a set, such that no ...
- 前端JQuery中获取一个div下的多个id值
获取所有的Id值,方法是通过div.class获取全局的值,然后再提取具体的Id值 方法一:用for循环,因为$("div.class")获取的是一个数组,通过循环读取出数组中的每 ...
- 软工实践 - 第二十八次作业 Beta 冲刺(6/7)
队名:起床一起肝活队 组长博客:https://www.cnblogs.com/dawnduck/p/10146478.html 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过 ...
- Jboss6内存修改
1.启动脚本:/home/jboss/jboss-eap-6.2/bin/standalone.sh -Djboss.bind.address.management=192.168.0.62 -Djb ...