【GDKOI2014模拟】树的直径
2017-12-04 12:16
260 查看
题目大意:
并不想讲。题解:
树的直径有一个性质。现在有两棵树,如果把它们随意连一条边,会变成一棵树,新树的直径的端点一定是之前两棵树的直径的共4个端点的两个。
所以这题搞个倍增就可以在线了。
Code:
#include<cstdio> #include<algorithm> #define fo(i, x, y) for(int i = x; i <= y; i ++) #define fd(i, x, y) for(int i = x; i >= y; i --) #define max(a, b) ((a) > (b) ? (a) : (b)) using namespace std; const int N = 500000; int n, a , tot; int son [2], dep ; int f[17] , ans; int lca(int x, int y) { if(dep[x] < dep[y]) swap(x, y); fd(i, 16, 0) if(dep[f[i][x]] >= dep[y]) x = f[i][x]; if(x == y) return x; fd(i, 16, 0) if(f[i][x] != f[i][y]) x = f[i][x], y = f[i][y]; return f[0][x]; } int dis(int x, int y) { int lc = lca(x, y); return dep[x] + dep[y] - 2 * dep[lc]; } int main() { scanf("%d", &n); tot = 4; dep[1] = 1; dep[2] = dep[3] = dep[4] = 2; f[0][2] = f[0][3] = f[0][4] = 1; int p = 2, q = 4; fo(i, 1, n) { scanf("%d", &a[i]); son[a[i]][0] = ++ tot; son[a[i]][1] = ++ tot; dep[tot - 1] = dep[tot] = dep[a[i]] + 1; f[0][tot - 1] = f[0][tot] = a[i]; fo(j, 1, 16) f[j][tot - 1] = f[j - 1][f[j - 1][tot - 1]], f[j][tot] = f[j - 1][f[j - 1][tot]]; if(dis(p, tot) < dis(q, tot)) swap(p, q); if(dis(p, q) < dis(p, tot)) q = tot; ans = max(ans, dis(p, q)); printf("%d\n", ans); } }
相关文章推荐
- [ZOJ3555][GDKOI2014模拟]树的直径
- jzoj3555 【GDKOI2014模拟】树的直径 lca+离线
- [jzoj]3555. 【GDKOI2014模拟】树的直径(结论题-树的性质)
- HDU 5122 K.Bro Sorting(2014北京区域赛现场赛K题 模拟)
- 3785. 【NOIP2014模拟8.19】分数
- JZOJ 3775. 【NOIP2014模拟8.15】因子的排列
- hdu 4915 Parenthese sequence(模拟)2014多校训练第5场
- jzoj3782 [NOIP2014模拟8.17] 组队
- NOIP2014提高组模拟8.9
- JZOJ 3806. 【NOIP2014模拟8.24】小X 的道路修建
- 【NOIP2014模拟8.25】地砖铺设
- [GDKOI模拟2016.01.26][JZOJ4218]补给站
- 【NOIP2014模拟8.25】设备塔
- PKU Campus 2014 B:An Easy Task(模拟)
- 【模拟】BAPC2014 G Growling Gears (Codeforces GYM 100526)
- JZOJ3885. 【长郡NOIP2014模拟10.22】搞笑的代码
- 【NOIP2014模拟】邻近(near)
- 【NOIP2014模拟11.2A组】国色天香 (Standard IO)
- JZOJ 3927. 【NOIP2014模拟11.6】可见点数
- 3928. 【NOIP2014模拟11.6】射击