容易写出nQ的暴力 由于数据是期望的时间 所以直接dfs可以跑的很快 可以拿到70分。

当然 可以进一步优化暴力 使用换根dp 然后可以将暴力优化到n^2.

const int MAXN=300010;
int n,Q,T,len,maxx;
int lin[MAXN],d[MAXN],ver[MAXN<<1],nex[MAXN<<1];
inline void add(int x,int y)
{
ver[++len]=y;
nex[len]=lin[x];
lin[x]=len;
}
inline void dfs(int x,int y)
{
d[x]=d[y]+1;
maxx=max(maxx,d[x]-1);
go(x)if(tn!=y)dfs(tn,x);
}
int main()
{
freopen("hike.in","r",stdin);
freopen("hike.out","w",stdout);
get(T);get(n);get(Q);
rep(1,Q,i)
{
int op,x,y;
get(op);get(x)^(T*maxx);
if(op==1)get(y)^(T*maxx),add(x,y),add(y,x);
else maxx=0,dfs(x,0),put(maxx);
}
return 0;
}

考虑 离线。可以发现 每次还是需要暴力。

进一步思考 树上和一个点的最远点有什么特殊性质。

不难想到树的直径 可以发现 一个点的最远点一定是直降两端之一.

这个不难证明。分情况讨论 这条路径是否穿过直径来讨论。

那么其实我们要维护一个联通树的直降两端即可。

离线可以先把树给建出来。

然后 合并两个集合的最远点也比较简单 可以证明 新的直径的两端在这4个点之中。

至于证明和上面差不多 也是分类讨论。

这样我们可以利用原树的倍增数组来求两点之间距离。

考虑在线 发现两点距离难求出 考虑启发式合并 然后暴力重新处理倍增数组。

这样每个点最多被重构logn次每次倍增数组的更新 也就是nlog^2+Qlogn 这个虽然已经可以通过了。

但是 考虑更优的做法。

维护树的联通性 容易想到 LCT.

连边的时候 维护一下这个连通块的直径端点即可。两点之间的距离也比较好求。

一个设为根 一个access 最后查splay大小即可。

复杂度 nlogn+Qlogn.

const int MAXN=300010;
int n,Q,T,maxx,top;
int f[MAXN],L[MAXN],s[MAXN],R[MAXN],re[MAXN],fa[MAXN],c[MAXN][2],sz[MAXN];//sz[x]表示x所在splay中的节点个数.
inline int getfather(int x){return x==fa[x]?x:fa[x]=getfather(fa[x]);}
inline int pd(int x){return c[f[x]][1]==x||c[f[x]][0]==x;}
inline void rev(int x)
{
if(!x)return;
swap(c[x][0],c[x][1]);
re[x]^=1;
}
inline void pushup(int x)
{
sz[x]=sz[c[x][0]]+sz[c[x][1]]+1;
}
inline void pushdown(int x){if(re[x])rev(c[x][0]),rev(c[x][1]),re[x]=0;}
inline void rotate(int x)
{
int old=f[x],oldf=f[old],k=c[old][1]==x;
c[old][k]=c[x][k^1];c[x][k^1]=old;
if(pd(old))c[oldf][c[oldf][1]==old]=x;
if(c[old][k])f[c[old][k]]=old;
f[old]=x;f[x]=oldf;pushup(old);
}
inline void splay(int x)
{
int y=x;top=0;
s[++top]=y;
while(pd(y))s[++top]=y=f[y];
while(top)pushdown(s[top--]);
while(pd(x))
{
int old=f[f[x]];
if(pd(f[x]))rotate(((c[f[x]][0]==x)^(c[old][0]==f[x]))?x:f[x]);
rotate(x);
}
pushup(x);return;
}
inline void access(int x)
{
for(int y=0;x;x=f[y=x])
{
splay(x);
c[x][1]=y;
pushup(x);
}
}
inline void make_root(int x)
{
access(x);splay(x);
rev(x);
}
inline int dis(int x,int y)
{
make_root(x);
access(y);
splay(y);
return sz[y];
}
inline void merge(int x,int y)
{
int xx=getfather(x);
int yy=getfather(y);
int s1,s2,s3,s4;
s1=L[xx],s2=L[yy];
s3=R[xx],s4=R[yy];
int l=0,r=0,w=0;
int ww=dis(s1,s2);
if(ww>w)w=ww,l=s1,r=s2;
ww=dis(s1,s3);
if(ww>w)w=ww,l=s1,r=s3;
ww=dis(s1,s4);
if(ww>w)w=ww,l=s1,r=s4;
ww=dis(s2,s3);
if(ww>w)w=ww,l=s2,r=s3;
ww=dis(s2,s4);
if(ww>w)w=ww,l=s2,r=s4;
ww=dis(s3,s4);
if(ww>w)w=ww,l=s3,r=s4;
fa[xx]=yy;L[yy]=l;R[yy]=r;
}
inline void LINK(int x,int y)
{
make_root(x);f[x]=y;
merge(x,y);
}
int main()
{
freopen("1.in","r",stdin);
get(T);get(n);get(Q);
rep(1,n,i)sz[i]=1,L[i]=R[i]=i,fa[i]=i;
rep(1,Q,i)
{
int op,x,y;
get(op);get(x)^(T*maxx);
if(op==1)get(y)^(T*maxx),LINK(x,y);
else
{
int xx=getfather(x);
maxx=max(dis(x,L[xx]),dis(x,R[xx]))-1;
put(maxx);
}
}
return 0;
}

4.17 省选模拟赛 远行 LCT 启发式合并 倍增的更多相关文章

  1. 5.20 省选模拟赛 T1 图 启发式合并 线段树合并 染色计数问题

    LINK:图 在说这道题之前吐槽一下今天的日子 520 = 1+1+4+514. /cy 这道题今天做的非常失败 一点分都没拿到手 关键是今天的T3 把我整个人给搞崩了. 先考虑 如果得到了这么一张图 ...

  2. 3.28 省选模拟赛 染色 LCT+线段树

    发现和SDOI2017树点涂色差不多 但是当时这道题模拟赛的时候不会写 赛后也没及时订正 所以这场模拟赛的这道题虽然秒想到了LCT和线段树但是最终还是只是打了暴力. 痛定思痛 还是要把这道题给补了. ...

  3. 6.18 省选模拟赛 字符串 LCT SAM

    LINK:字符串 看起来很难做 考虑一种暴力 建立SAM后每次查询暴力扫儿子. 期望得分10分.实际得分10分. 另外一种发现每次扫儿子过于暴力 可以每次儿子向上做贡献 每次都暴力向上跳. 期望得分1 ...

  4. 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解

    今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...

  5. [BZOJ4530][Bjoi2014]大融合 LCT + 启发式合并

    [BZOJ4530][Bjoi2014]大融合 试题描述 小强要在N个孤立的星球上建立起一套通信系统.这套通信系统就是连接N个点的一个树. 这个树的边是一条一条添加上去的.在某个时刻,一条边的负载就是 ...

  6. @省选模拟赛03/16 - T3@ 超级树

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 一棵 k-超级树(k-SuperTree) 可按如下方法得到:取 ...

  7. CF827D Best Edge Weight[最小生成树+树剖/LCT/(可并堆/set启发式合并+倍增)]

    题意:一张图求每条边边权最多改成多少可以让所有MST都包含这条边. 这题还是要考察Kruskal的贪心过程. 先跑一棵MST出来.然后考虑每条边. 如果他是非树边,要让他Kruskal的时候被选入,必 ...

  8. BZOJ2888 资源运输(LCT启发式合并)

    这道题目太神啦! 我们考虑他的每一次合并操作,为了维护两棵树合并后树的重心,我们只好一个一个的把节点加进去.那么这样一来看上去似乎就是一次操作O(nlogn),但是我们拥有数据结构的合并利器--启发式 ...

  9. BZOJ.3510.首都(LCT 启发式合并 树的重心)

    题目链接 BZOJ 洛谷 详见这. 求所有点到某个点距离和最短,即求树的重心.考虑如何动态维护. 两棵子树合并后的重心一定在两棵树的重心之间那条链上,所以在合并的时候用启发式合并,每合并一个点检查sz ...

随机推荐

  1. html table表格斜线表头的实现方法总汇

    在html中给table加一个斜线的表头有时是很有必要的,但是到底该怎么实现这种效果呢?总结了以下几种方法: 1.UI背景图实现 直接去找公司的UI,让她做一张图片,作为背景图片放到这里,然后撑满就可 ...

  2. Kail安装VMtools

    0x00 前言 之前用吾爱的xp虚拟机,总是装不上vmtools,真是难受.每次跨机器粘贴复制都一件极其痛苦的事,而且虚拟机还不能直接浏览硬盘上的文件.虽说安全性保证了,但是这是真的痛苦.这两天开始用 ...

  3. 准备开始了解orchardcore,有兴趣的一起啊

    orchardcore网上的资料真是少,开始看源码,目前遇到的最大问题是不知道ModuleName属性如何自动注入到OrchardCore.Cms.Web的程序集Assembly上面,等这个搞通了估计 ...

  4. 006.Nginx访问控制

    一 Nginx连接限制 1.1 HTTP协议的连接与请求 HTTP是建立在TCP, 一次HTTP请求需要先建立TCP三次握手(称为TCP连接),在连接的基础上再进行HTTP请求. HTTP请求建立在一 ...

  5. JS基础知识点(一)

    原始类型 null undefined boolean number string symbol 注意 原始类型存储的都是值,是没有函数可以调用的,但实际上除null和undefined外,其他类型使 ...

  6. Python之函数、递归、内置函数

    本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 温故知新 1. 集合 主要作用: 去重 关系测 ...

  7. Elasticsearch恢复备份的数据

    1.恢复备份好的snapshot 1.1恢复snapshot_1下的所有index POST _snapshot/my_backup/snapshot_1/_restore 1.2恢复snapshot ...

  8. 计算机网络学习socket--day1

    socket编程 socket可以看成是用户进程与内核网络协议栈的编程接口 socket不仅可以用于本机的进程间通信,还可以用于网络上不同主机的进程间通信 socket全双工通信 在异构系统间进行通信 ...

  9. 如何理解Javascript中的函数(Function)

    Function类型 首先得知道,每个函数都是Function类型的实例,所以函数本身是对象. 示例1: function sum (num1, num2){ return sum1 + sum2; ...

  10. 围绕一个 volatile 关键字居然可以问出来 16 个问题

    对于 Java 每次面试就会想到多线程,多线程问题基本跑不了要问一下 volalite 关键字,可是我万万没想到居然一个 volatile 关键字可以连续问题出来 16 个问题!看下你能回答出来几个? ...