CodeForces 379F 树的直径 New Year Tree

题意:每次操作新加两个叶子节点,每次操作完以后询问树的直径。

维护树的直径的两个端点U,V,每次计算一下新加进来的叶子节点到U,V两点的距离,如果有更长的就更新。

因为根据树的直径的求法,若出现新的直径,一定是到U或者到V距离最远。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5
 6 const int maxn = 1000000 + 1000;
 7 const int logmaxn = 20;
 8
 9 int n, Q;
10
11 int L[maxn];
12 int fa[maxn];
13 int anc[maxn][logmaxn];
14
15 void add(int u, int pa)
16 {
17     fa[u] = pa;
18     L[u] = L[pa] + 1;
19     anc[u][0] = pa;
20     for(int j = 1; (1 << j) < n; j++) if(anc[u][j-1])
21         anc[u][j] = anc[anc[u][j-1]][j-1];
22 }
23
24 int LCA(int p, int q)
25 {
26     if(L[p] < L[q]) std::swap(p, q);
27     int log;
28     for(log = 1; (1 << log) <= L[p]; log++); log--;
29     for(int i = log; i >= 0; i--)
30         if(L[p] - (1 << i) >= L[q]) p = anc[p][i];
31     if(p == q) return p;
32     for(int i = log; i >= 0; i--)
33         if(anc[p][i] && anc[p][i] != anc[q][i])
34             p = anc[p][i], q = anc[q][i];
35     return fa[p];
36 }
37
38 int distance(int u, int v)
39 {
40     int l = LCA(u, v);
41     return L[u] + L[v] - L[l] * 2;
42 }
43
44 int main()
45 {
46     scanf("%d", &Q);
47     n = 4;
48     fa[2] = fa[3] = fa[4] = 1;
49     L[2] = L[3] = L[4] = 1;
50     anc[2][0] = anc[3][0] = anc[4][0] = 1;
51
52     int U = 2, V = 3, diameter = 2;
53     while(Q--)
54     {
55         int p; scanf("%d", &p);
56         add(++n, p);
57         add(++n, p);
58         int l1 = distance(n, U), l2 = distance(n, V);
59         if(l1 >= l2 && l1 >= diameter)
60         {
61             V = n;
62             diameter = l1;
63         }
64         else if(l2 >= l1 && l2 >= diameter)
65         {
66             U = n;
67             diameter = l2;
68         }
69         printf("%d\n", diameter);
70     }
71
72     return 0;
73 }

代码君

时间: 2024-08-26 11:11:24

CodeForces 379F 树的直径 New Year Tree的相关文章

CodeForces 14D 树的直径 Two Paths

给出一棵树,找出两条不相交即没有公共点的路径,使得两个路径的长度的乘积最大. 思路:枚举树中的边,将该边去掉,分成两棵树,分别求出这两棵树的直径,乘起来维护一个最大值即可. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 7 const int maxn = 200 + 10; 8 9

codeforces 14D 树的直径

题目大意:给你一棵树,要进行两次访问,两次访问中不能重复访问任一节点和边,问两次访问的最大长度乘积,每边 长度为1 思路:因为n只有200,所以可以枚举从哪里将树分成两棵树即删除一条边,求两棵树的直径,维护乘积最大值即可.树的直径在以前的博文讲过,两遍dfs即可 #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <fstream>

codeforces GYM 100114 J. Computer Network tarjan 树的直径 缩点

J. Computer Network Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Description The computer network of “Plunder & Flee Inc.” consists of n servers and m two-way communication links. Two servers can communicate either thr

codeforces GYM 100114 J. Computer Network 无相图缩点+树的直径

题目链接: http://codeforces.com/gym/100114 Description The computer network of “Plunder & Flee Inc.” consists of n servers and m two-way communication links. Two servers can communicate either through a direct link, or through a chain of links, by relayi

codeforces 455C C. Civilization(树形dp+树的直径+并查集)

题目链接: codeforces 455C 题目大意: 给出一些点,他们之间初始存在一些边,给出两种操作,第一种是查询某个点所在的树的直径,另一种是将两个树合并,要求使合并后的树的直径最小. 题目分析: 首先算取没做操作前的连通块里的树的直径,也就是先dfs一遍,找到深度最大的点,然后从这个点再搜,找到的最远的距离就是这棵树的直径,因为可以证明从根搜深度最大的点一定是树的直径的一个端点,因为它可以通过到达次大的深度的点或者找到与它公共祖先不在根处的获得树的直径. 然后每次合并,我们可以知道得到的

URAL 1752. Tree 2 树的直径+LCA倍增

题目来源:URAL 1752. Tree 2 题意:求一个点v与它距离为d的任意一个点 没有输出0 思路:开始想倍增法 但是倍增法只能往他的祖先去 后来百度发现了树的直径 想了想 发现可以建2棵树 每一棵树的根是树的直径的2个端点 这样保证了每个点和他距离最远的点就是其中一个根 因为一个点到树的直径的端点的距离是最远的 最后就是LCA倍增了 #include <cstdio> #include <cstring> #include <algorithm> #includ

light oj 1094 Farthest Nodes in a Tree(树的直径模板)

1094 - Farthest Nodes in a Tree PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB Given a tree (a connected graph with no cycles), you have to find the farthest nodes in the tree. The edges of the tree are weighted and undire

lightoj-1094 Farthest Nodes in a Tree(求树的直径)

1094 - Farthest Nodes in a Tree PDF (English) Statistics ForumTime Limit: 2 second(s) Memory Limit: 32 MBGiven a tree (a connected graph with no cycles), you have to find the farthest nodes in the tree. The edges of the tree are weighted and undirect

Codeforces 14D Two Paths 树的直径

题目链接:点击打开链接 题意:给定一棵树 找2条点不重复的路径,使得两路径的长度乘积最大 思路: 1.为了保证点不重复,在图中删去一条边,枚举这条删边 2.这样得到了2个树,在各自的树中找最长链,即树的直径,然后相乘即可 #include<stdio.h> #include<iostream> #include<string.h> #include<set> #include<vector> #include<map> #includ