题意翻译

你是一个程序猿,现在有一棵新年树(并不是传统的带着叶子的树)——它有四个节点: 1,2,3,4. 其中2,3,4的父亲都是1.

新年里,程序猿们往往会做一些有趣的事情。你则选择以往这棵树上加节点来取乐。 一个添加节点的操作是这样的:

1) 找到树上的一个叶子结点v

2) 设现在树上有n个节点,那么你现在会加入两个节点n+1和n+2,它们都会成为n的儿子.

你的任务是在做q次这样的操作,并在每做完一次后计算一次树的直径。来吧,我们一起来解决这道新年问题吧!

输入:

第一行一个整数\(q (1 ≤ q ≤ 5×10^5)\) ,表示操作次数。接下来q行,每行一个数v,表示你当前操作的节点。保证它一定是一个叶子结点。

输出:

q行,每行一个数,表示做了这个操作以后树的直径。


有一个小结论就是在合并两个树的时候

新合并出来的树的直径的两个端点一定是两个原树的直径的端点,因为只有6种方案,所以暴力判断一下就好了

先离线处理出整棵树,合并时用并查集合并

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
const int M = 1000005 ;
using namespace std ;
inline int read() {
char c = getchar() ; int x = 0 , w = 1 ;
while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; }
return x*w ;
}
int n , m , hea[M] , num , q[M] , dep[M] , st[M][20] ;
int l[M] , r[M] , to[M] , f[M] , Res[M] ;
struct E { int Nxt , to ; } edge[M << 1] ;
inline void add_edge(int from , int to) {
edge[++num].Nxt = hea[from] ;
edge[num].to = to ; hea[from] = num ;
}
int find(int x) { if(f[x] != x) f[x] = find(f[x]) ; return f[x] ; }
void Dfs(int u , int father , int depth) {
dep[u] = depth ; st[u][0] = father ;
for(int i = hea[u] , v ; i ; i = edge[i].Nxt) {
v = edge[i].to ;
if(v == father) continue ;
Dfs(v , u , depth + 1) ;
}
}
inline void ST() {
for(int j = 1 ; j <= 19 ; j ++)
for(int i = 1 ; i <= n ; i ++)
st[i][j] = st[st[i][j - 1]][j - 1] ;
}
inline int LCA(int u , int v) {
if(dep[u] < dep[v]) swap(u , v) ;
for(int i = 19 ; i >= 0 ; i --)
if(dep[st[u][i]] >= dep[v])
u = st[u][i] ;
if(u == v) return u ;
for(int i = 19 ; i >= 0 ; i --)
if(st[u][i] != st[v][i])
u = st[u][i] , v = st[v][i] ;
return st[u][0] ;
}
int u , v , Ans , el , er , d ;
inline void Solve(int x , int y) {
u = find(x) , v = find(y) ;
Ans = 0 , el = 0 , er = 0 , d = 0 ;
Ans = dep[l[u]] + dep[r[u]] - (dep[LCA(l[u] , r[u])] << 1) , el = l[u] , er = r[u] ;
d = dep[l[v]] + dep[r[v]] - (dep[LCA(l[v] , r[v])] << 1) ;
if(d > Ans) Ans = d , el = l[v] , er = r[v] ;
d = dep[l[u]] + dep[l[v]] - (dep[LCA(l[u] , l[v])] << 1) ;
if(d > Ans) Ans = d , el = l[u] , er = l[v] ;
d = dep[l[u]] + dep[r[v]] - (dep[LCA(l[u] , r[v])] << 1) ;
if(d > Ans) Ans = d , el = l[u] , er = r[v] ;
d = dep[l[v]] + dep[r[u]] - (dep[LCA(l[v] , r[u])] << 1) ;
if(d > Ans) Ans = d , el = l[v] , er = r[u] ;
d = dep[r[u]] + dep[r[v]] - (dep[LCA(r[u] , r[v])] << 1) ;
f[v] = u ; l[u] = el , r[u] = er ;
}
int main() {
m = read() ; n = 1 ;
q[1] = 1 ; q[2] = 1 ;
to[1] = ++ n ; add_edge(1 , to[1]) ; add_edge(to[1] , 1) ;
to[2] = ++ n ; add_edge(1 , to[2]) ; add_edge(to[2] , 1) ;
to[3] = ++ n ; add_edge(1 , to[3]) ; add_edge(to[3] , 1) ;
for(int i = 3 ; i <= m + 2 ; i ++) {
q[i] = read() ;
to[i * 2 - 1] = ++ n ; add_edge(q[i] , to[i * 2 - 1]) ; add_edge(to[i * 2 - 1] , q[i]) ;
to[i << 1] = ++ n ; add_edge(q[i] , to[i << 1]) ; add_edge(to[i << 1] , q[i]) ;
}
for(int i = 1 ; i <= n ; i ++) f[i] = i , l[i] = i , r[i] = i ;
Dfs(1 , 1 , 1) ; ST() ;
for(int i = 1 ; i <= m + 3 ; i ++) {
Solve(q[i] , to[i * 2 - 1]) ;
if(i == 2) continue ;
Solve(q[i] , to[i << 1]) ;
if(i > 2) {
int u = find(q[i]) ;
Res[i - 2] = dep[l[u]] + dep[r[u]] - (dep[LCA(l[u] , r[u])] << 1) ;
}
}
for(int i = 1 ; i <= m ; i ++) printf("%d\n",Res[i]) ;
return 0 ;
}

CF379F New Year Tree的更多相关文章

  1. cf379F New Year Tree (树的直径+倍增lca)

    可以证明,如果合并两棵树,新的直径的端点一定是原来两树中直径的端点 可以把新加两个点的操作看成是把两个只有一个点的树合并到原来的树上,然后用其中的一个点去和原来树上的直径两端点更新直径就可以了 #in ...

  2. [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法

    二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...

  3. SAP CRM 树视图(TREE VIEW)

    树视图可以用于表示数据的层次. 例如:SAP CRM中的组织结构数据可以表示为树视图. 在SAP CRM Web UI的术语当中,没有像表视图(table view)或者表单视图(form view) ...

  4. 无限分级和tree结构数据增删改【提供Demo下载】

    无限分级 很多时候我们不确定等级关系的层级,这个时候就需要用到无限分级了. 说到无限分级,又要扯到递归调用了.(据说频繁递归是很耗性能的),在此我们需要先设计好表机构,用来存储无限分级的数据.当然,以 ...

  5. 2000条你应知的WPF小姿势 基础篇<45-50 Visual Tree&Logic Tree 附带两个小工具>

    在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000Things You Should Know About C# 和 2,0 ...

  6. Leetcode 笔记 110 - Balanced Binary Tree

    题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...

  7. Leetcode 笔记 100 - Same Tree

    题目链接:Same Tree | LeetCode OJ Given two binary trees, write a function to check if they are equal or ...

  8. Leetcode 笔记 99 - Recover Binary Search Tree

    题目链接:Recover Binary Search Tree | LeetCode OJ Two elements of a binary search tree (BST) are swapped ...

  9. Leetcode 笔记 98 - Validate Binary Search Tree

    题目链接:Validate Binary Search Tree | LeetCode OJ Given a binary tree, determine if it is a valid binar ...

随机推荐

  1. IDA-IDC脚本编写语法

    1.IDA脚本编写基础 IDC是IDA内置的脚本语言,其语法与C非常相似,它是一种解释性语言. 执行方法 在IDA中按SHIFT+F2键会弹出一个对话框,把语句直接写在对话框中,点击run就可被运行. ...

  2. 静态区间第k大(划分树)

    POJ 2104为例[经典划分树问题] 思想: 利用快速排序思想, 建树时将区间内的值与区间中值相比,小于则放入左子树,大于则放入右子树,如果相等则放入左子树直到放满区间一半. 查询时,在建树过程中利 ...

  3. [bzoj2882]工艺_后缀数组

    工艺 bzoj-2882 题目大意:题目链接. 注释:略. 想法: 跟bzoj1031差不多啊. 把串倍长后扫$sa$数组. 最后再统计答案即可. Code: #include <iostrea ...

  4. Spring boot精要

    1.自动配置:针对很多Spring应用程序的常见应用功能,SpringBoot能自动提供相关配置: 2.起步依赖:告诉SpringBoot需要什么功能,他就能引入需要的库: 3.命令行界面:这是Spr ...

  5. 物理内存、虚拟内存、buffers、cached、共享内存、swap

    物理内存: 实际使用的内存: 虚拟内存: 虚拟内存是操作系统内核为了对进程地址空间进行管理(process address space management)而精心设计的一个逻辑意义上的内存空间概念. ...

  6. C#使用全局钩子(hook),SetWindowsHookEx返回0、不回调的解决

    http://www.csharpwin.com/csharpspace/3766r5747.shtml 在.net 2005平台下 在使用全局hook时,总是遇见SetWindowsHookEx的返 ...

  7. 012 router password

    Press RETURN to get started!       Router>en Router#config t Enter configuration commands, one pe ...

  8. CentOS 查看日志命令

    cat tail -f 日 志 文 件 说    明 /var/log/message 系统启动后的信息和错误日志,是Red Hat Linux中最常用的日志之一 /var/log/secure 与安 ...

  9. 《从零開始学Swift》学习笔记(Day67)——Cocoa Touch设计模式及应用之MVC模式

    原创文章,欢迎转载.转载请注明:关东升的博客   MVC(Model-View-Controller,模型-视图-控制器)模式是相当古老的设计模式之中的一个,它最早出如今Smalltalk语言中. 如 ...

  10. 【WinHec启发录】透过Windows 10技术布局,谈微软王者归来

    每一个时代都有王者,王者的成功,往往是由于恰逢其时地公布了一个成功的产品(具有里程碑意义,划时代的产品).Windows 95的成功标示着微软是PC时代的王者:WinXP的成功标示着微软是互联网时代的 ...