题目描述

Miranda 生活的城市有 \(N\) 个小镇,一开始小镇间没有任何道路连接。随着经济发现,小镇之间陆续建起了一些双向的道路但是由于经济不太发达,在建设过程中,会保证对于任意两个小镇,最多有一条路径能互相到达。有的时候 Miranda 会从某个小镇开始进行徒步旅行,每次出发前,她都想选择一个她能到达的最远的小镇作为终点,并且她在行走过程中是不会走回头路的,为了估算这次旅行的时间,她会需要你告诉她这次旅行的时间会是多少呢?可以假设通过每条道路都需要单位时间,并且 Miranda 不会在小镇停留。

输入格式

第一行一个整数 \(\text{type}\),表示数据类型。

第二行两个整数 \(N\)、\(Q\) 。

接下来 \(Q\) 行,每行先读入一个整数 \(t\) ,若 \(t = 1\) ,则接下来读入两个整数 \(u\) 、\(v\) ,表示小镇 \(u\) 与小镇 \(v\) 建立了一条新道路。若 \(t = 2\) ,读入一个整数 \(u\) ,表示 Miranda 要开始一次从小镇 \(u\) 出发的旅行。

  • 若 \(\text{type} = 1\) ,记 \(\text{lastAns}\) 表示最近一次 Miranda 旅行的时间,那么对于每次操作的 \(u\) 或 \(u, v\) ,都要异或上 \(\text{lastAns}\) 。

  • 若 \(\text{type} = 0\) ,则不需要对数据进行处理。

输出格式

对于每次询问,输出 Miranda 能到达的最远的小镇的距离是多少。注意 Miranda 可能只能留在开始的小镇。

样例

样例输入

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

样例输出

0
1
0
3
2
3

数据范围与提示

对于 \(20\%\) 的数据,\(N \leq 5000, Q \leq 10000\) ;

对于 \(50\%\) 的数据,\(N \leq 100000, Q \leq 200000\) ;

对于另外 \(20\%\) 的数据,\(\text{type} = 0\) ;

对于 \(100\%\) 的数据,\(N \leq 300000, Q \leq 500000, \text{type} \in \{ 0, 1 \}\) ,解密后的 \(u\) 、\(v\) 满足 \(1 \leq u, v \leq N\) ,且道路的修建会满足:每一时刻,都不存在 \(u, v\) 使得 \(u, v\) 之间能通过多种方式到达。

题解

直径的性质:

  1. 与一个点距离最大的点为任意一条直径的两个端点之一

  2. 两棵树之间连一条边,新树直径的两个端点一定为第一棵树直径的两个端点和第二棵树直径的两个端点这四者中之二

所以用LCT维护联通块直径的两个端点

查询时,把查询的点与两个端点分别split再询问size大小,取max即为答案

修改时,取出两个合并的联通块的直径的端点,四个,讨论6种情况,取距离最大的两个点为新的直径的端点

就这样就做完了

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=300000+10;
int n,q,res,p1,p2,fa[MAXN],type,lastans;
std::pair<int,int> d[MAXN];
#define lc(x) ch[(x)][0]
#define rc(x) ch[(x)][1]
struct LinkCut_Tree{
int size[MAXN],ch[MAXN][2],fa[MAXN],rev[MAXN],stack[MAXN],cnt;
inline bool nroot(int x)
{
return lc(fa[x])==x||rc(fa[x])==x;
}
inline void reverse(int x)
{
std::swap(lc(x),rc(x));
rev[x]^=1;
}
inline void pushup(int x)
{
size[x]=size[lc(x)]+size[rc(x)]+1;
}
inline void pushdown(int x)
{
if(rev[x])
{
if(lc(x))reverse(lc(x));
if(rc(x))reverse(rc(x));
rev[x]=0;
}
}
inline void rotate(int x)
{
int f=fa[x],p=fa[f],c=(rc(f)==x);
if(nroot(f))ch[p][rc(p)==f]=x;
fa[ch[f][c]=ch[x][c^1]]=f;
fa[ch[x][c^1]=f]=x;
fa[x]=p;
pushup(f);
pushup(x);
}
inline void splay(int x)
{
cnt=0;
stack[++cnt]=x;
for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i];
while(cnt)pushdown(stack[cnt--]);
for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
if(nroot(y))rotate((lc(fa[y])==y)==(lc(y)==x)?y:x);
pushup(x);
}
inline void access(int x)
{
for(register int y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x);
}
inline void makeroot(int x)
{
access(x);splay(x);reverse(x);
}
inline void split(int x,int y)
{
makeroot(x);access(y);splay(y);
}
inline void link(int x,int y)
{
makeroot(x);fa[x]=y;pushup(y);
}
};
LinkCut_Tree T;
#undef lc
#undef rc
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline int found(int x)
{
if(fa[x]!=x)fa[x]=found(fa[x]);
return fa[x];
}
inline void length(int x,int y)
{
T.split(x,y);
if(T.size[y]>res)res=T.size[y],p1=x,p2=y;
}
#define ft first
#define sd second
inline void modify(int x,int y)
{
std::pair<int,int> a=d[found(x)],b=d[found(y)];
res=0;T.link(x,y);
length(a.ft,a.sd);length(a.ft,b.ft);length(a.ft,b.sd);
length(a.sd,b.ft);length(a.sd,b.sd);length(b.ft,b.sd);
d[found(y)]=std::make_pair(p1,p2);
fa[found(x)]=found(y);
}
#undef ft
#undef sd
int main()
{
read(type);
read(n);read(q);
for(register int i=1;i<=n;++i)fa[i]=i,d[i]=std::make_pair(i,i);
while(q--)
{
int opt;read(opt);
if(opt==1)
{
int u,v;read(u);read(v);
if(type)u^=lastans,v^=lastans;
modify(u,v);
}
if(opt==2)
{
int u,ans=0;read(u);
if(type)u^=lastans;
std::pair<int,int> now=d[found(u)];
T.split(now.first,u);chkmax(ans,T.size[u]);
T.split(now.second,u);chkmax(ans,T.size[u]);
write(lastans=ans-1,'\n');
}
}
return 0;
}

【刷题】LOJ 6038 「雅礼集训 2017 Day5」远行的更多相关文章

  1. LOJ#6038. 「雅礼集训 2017 Day5」远行(LCT)

    题面 传送门 题解 要不是因为数组版的\(LCT\)跑得实在太慢我至于去学指针版的么--而且指针版的完全看不懂啊-- 首先有两个结论 1.与一个点距离最大的点为任意一条直径的两个端点之一 2.两棵树之 ...

  2. LOJ#6038. 「雅礼集训 2017 Day5」远行 [LCT维护子树的直径]

    树的直径一定是原联通块4个里的组合 1.LCT,维护树的直径,这题就做完了 2.直接倍增,lca啥的求求距离,也可以吧- // powered by c++11 // by Isaunoya #inc ...

  3. loj#6038 「雅礼集训 2017 Day5」远行

    分析 代码 #include<bits/stdc++.h> using namespace std; #define fi first #define se second #define ...

  4. loj#6040. 「雅礼集训 2017 Day5」矩阵(线性代数+递推)

    题面 传送门 题解 我的线代学得跟屎一样看题解跟看天书一样所以不要指望这题我会写题解 这里 //minamoto #include<bits/stdc++.h> #define R reg ...

  5. @loj - 6039@ 「雅礼集训 2017 Day5」珠宝

    目录 @description@ @solution@ @accpeted code@ @details@ @description@ Miranda 准备去市里最有名的珠宝展览会,展览会有可以购买珠 ...

  6. [LOJ#6039].「雅礼集训 2017 Day5」珠宝[决策单调性]

    题意 题目链接 分析 注意到本题的 \(C\) 很小,考虑定义一个和 \(C\) 有关的状态. 记 \(f(x,j)\) 表示考虑到了价格为 \(x\) 的物品,一共花费了 \(j\) 元的最大收益. ...

  7. loj #6039 「雅礼集训 2017 Day5」珠宝 分组背包 决策单调性优化

    LINK:珠宝 去年在某个oj上写过这道题 当时懵懂无知wa的不省人事 终于发现这个东西原来是有决策单调性的. 可以发现是一个01背包 但是过不了 冷静分析 01背包的复杂度有下界 如果过不了说明必然 ...

  8. loj6038「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT

    题目传送门 https://loj.ac/problem/6038 题解 根据树的直径的两个性质: 距离树上一个点最远的点一定是任意一条直径的一个端点. 两个联通块的并的直径是各自的联通块的两条直径的 ...

  9. 【loj6038】「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT

    题目描述 给你 $n$ 个点,支持 $m$ 次操作,每次为以下两种:连一条边,保证连完后是一棵树/森林:询问一个点能到达的最远的点与该点的距离.强制在线. $n\le 3\times 10^5$ ,$ ...

随机推荐

  1. java阻塞队列之ArrayBlockingQueue

    在Java的java.util.concurrent包中定义了和多线程并发相关的操作,有许多好用的工具类,今天就来看下阻塞队列.阻塞队列很好的解决了多线程中数据的安全传输问题,其中最典型的例子就是客园 ...

  2. iOS 小技巧

    投影效果 scanBtn.layer.shadowColor = [UIColorblackColor].CGColor;//shadowColor阴影颜色     scanBtn.layer.sha ...

  3. OpenCL入门:(三:GPU内存结构和性能优化)

    如果我们需要优化kernel程序,我们必须知道一些GPU的底层知识,本文简单介绍一下GPU内存相关和线程调度知识,并且用一个小示例演示如何简单根据内存结构优化. 一.GPU总线寻址和合并内存访问 假设 ...

  4. ESP8266 NON-OS SDK 和 RTOS SDK实现GPIO中断不同点

    ESP8266 Non-OS SDK 和 RTOS SDK 实现GPIO的方法稍有不同: 对于 Non-OS SDK,比如需要把 MTDO 配置成输入,同时下降沿触发中断: gpio_init(voi ...

  5. MySQL5.6.14从安装到启动全过程

    1.下载 地址:http://dev.mysql.com/downloads/mysql/ 这里选择的是Linux-Generic平台,下载了MySQL-5.6.14-1.linux_glibc2.5 ...

  6. js页面跳转,url带url参数解决方案

    今天,在做一个项目的时候,向后端发送了一个Ajax请求,后端返回了一个字符串,告诉我未登录.那么我需要跳转到登录页面,同时告诉登录页面,登录成功后,需要跳回的url.也就是标题所说,url中的一个参数 ...

  7. jupyter通过notedown使用markdown

    0 Problem 最近看了下李沐老师的mxnet教程,在使用jupyter的时候打开教程发现全是markdown源文,没有展示markdown格式的文字. 1 Reason 源代码是用markdow ...

  8. ECharts之force力导向布局图——数据源说明及后端API约定

    Echarts ? 关于 Echarts 请移步这里 force 力导向图 实现方式,如: function require_EC () { require( [ 'echarts', //载入for ...

  9. TCP系列42—拥塞控制—5、Linux中的慢启动和拥塞避免(二)

    在本篇中我们继续上一篇文章wireshark的示例讲解,上一篇介绍了一个综合示例后,本篇介绍一些简单的示例,在读本篇前建议先把上一篇读完,为了节省篇幅,本篇只针对一些特殊的场景点报文进行讲解,不会像上 ...

  10. erlang node time ticket

    Erlang doesn't detect net splits by itself. You could start looking atnet_kernel:set_net_ticktime/2 ...