Codeforces 379 F. New Year Tree

## [$>Codeforces space 379 F. New Year Tree<$](http://codeforces.com/problemset/problem/379/F)

题目大意 : 有一棵有 (4) 个节点个树,有连边 ((1,2) (1,3) (1,4)) ,一共有 (q) 次操作,每次选择一个节点,新建两个节点 (n + 1, n + 2) 向其连边,每次操作完之后求树的直径的长度

$1 leq q leq 5 imes 10^5 $

解题思路 :

观察发现,每次加点后,树的直径的端点至多只会变化一个

证明:首先显然新的直径的端点不可能是两个新加的点,也不可能是两个原本不是直径端点的点

所以如果要使得新的直径的端点变化两个的话,那么必然有一个端点是新加的点

假设有新加的点 (u) ,其父亲是 (fa) ,离 (fa) 最远的点一定是树的直径的一个端点,那么此时离 (u) 最远的点也一定是树的直径一个端点. 至此产生矛盾,所以每次加点后,树的直径的端点至多只会变化一个

所以只需要每次加点动态维护倍增数组,用 (lca) 暴力判是否能更新掉一个直径端点即可,复杂度是 (O(nlogn))


/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
    int f = 0, ch = 0; x = 0;
    for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
    for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
    if(f) x = -x;
}
#define N (1000005)
int f[N][23], dep[N], tot; 
inline void addson(int u){
	int v = ++tot; 
	dep[v] = dep[u] + 1, f[v][0] = u;
	for(int j = 1; j <= 22; j++) f[v][j] = f[f[v][j-1]][j-1];
}
inline int Lca(int x, int y){
	if(dep[x] < dep[y]) swap(x, y);
	for(int i = 22; i >= 0; i--){
		if(dep[f[x][i]] >= dep[y]) x = f[x][i];
		if(dep[x] == dep[y]) break;
	}
	if(x == y) return x;
	for(int i = 22; i >= 0; i--)
		if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
	return f[x][0];
}
inline int dis(int x, int y){
	int lca = Lca(x, y); return dep[x] + dep[y] - 2 * dep[lca];	
}
int main(){
	dep[2] = dep[3] = dep[4] = 1;
	f[2][0] = f[3][0] = f[4][0] = 1, tot = 4;
	int n, l = 2, r = 4, ans = 2;
	read(n);
	for(int i = 1; i <= n; i++){
		int x; read(x);
		addson(x), addson(x);
		int nl = tot - 1, nr = tot;
		int s1 = dis(nl, r), s2 = dis(nl, l);
		int s3 = dis(nr, l), s4 = dis(nr, r);
		ans = Max(ans, Max(Max(s1, s2), Max(s3, s4)));
		if(ans == s1) l = nl;
		else if(ans == s2) r = nl;
		else if(ans == s3) r = nr;
		else if(ans == s4) l = nr;
		printf("%d
", ans); 
	}	
	return 0;
}
原文地址:https://www.cnblogs.com/mangoyang/p/9356990.html