(jzoj snow的追寻)线段树维护树的直径
2017-12-09 11:20
369 查看
jzoj snow的追寻
DFS序上搞
合并暴力和,记录最长链和当前最远点,距离跑LCA
DFS序上搞
合并暴力和,记录最长链和当前最远点,距离跑LCA
# include <stdio.h> # include <stdlib.h> # include <iostream> # include <algorithm> # include <string.h> # define IL inline # define RG register # define Fill(a, b) memset(a, b, sizeof(a)) using namespace std; typedef long long ll; IL ll Read(){ RG char c = getchar(); RG ll x = 0, z = 1; for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1; for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + c - '0'; return x * z; } const int MAXN(1e5 + 10); int n, ft[MAXN], cnt, Q; int size[MAXN], fa[MAXN], top[MAXN], son[MAXN], dfn[MAXN], ed[MAXN], id[MAXN], dep[MAXN]; struct Edge{ int to, nt; } edge[MAXN << 1]; struct Data{ int u, v, len; } t[MAXN << 2], ans; IL void Add(RG int u, RG int v){ edge[cnt] = (Edge){v, ft[u]}; ft[u] = cnt++; } IL void Dfs1(RG int u){ size[u] = 1; for(RG int e = ft[u]; e != -1; e = edge[e].nt){ RG int v = edge[e].to; if(size[v]) continue; dep[v] = dep[u] + 1; fa[v] = u; Dfs1(v); size[u] += size[v]; if(size[v] > size[son[u]]) son[u] = v; } } IL void Dfs2(RG int u, RG int Top){ top[u] = Top; dfn[u] = ++cnt; id[cnt] = u; if(son[u]) Dfs2(son[u], Top); for(RG int e = ft[u]; e != -1; e = edge[e].nt) if(!dfn[edge[e].to]) Dfs2(edge[e].to, edge[e].to); ed[u] = cnt; } IL ll Dis(RG int u, RG int v){ if(!u || !v) return 0; RG ll dis = dep[u] + dep[v]; while(top[u] != top[v]){ if(dep[top[u]] < dep[top[v]]) swap(u, v); u = fa[top[u]]; } if(dep[u] > dep[v]) swap(u, v); return dis - 2 * dep[u]; } IL Data Merge(RG Data x, RG Data y){ RG int p[4] = {x.u, x.v, y.u, y.v}; x.len = x.u = x.v = 0; for(RG int i = 0; i < 3; i++) for(RG int j = i + 1; j < 4; j++){ RG ll dis = Dis(p[i], p[j]); if(dis > x.len) x.len = dis, x.u = p[i], x.v = p[j]; } return x; } IL void Query(RG int x, RG int l, RG int r, RG int L, RG int R){ if(l >= L && r <= R) ans = Merge(ans, t[x]); else{ RG int mid = l + r >> 1; if(mid >= L) Query(x << 1, l, mid, L, R); if(mid < R) Query(x << 1 | 1, mid + 1, r, L, R); } } IL void Build(RG int x, RG int l, RG int r){ if(l == r) t[x].u = t[x].v = id[l], t[x].len = 0; else{ RG int mid = l + r >> 1, ls = x << 1, rs = x << 1 | 1; Build(ls, l, mid); Build(rs, mid + 1, r); t[x] = Merge(t[ls], t[rs]); } } int main(RG int argc, RG char* argv[]){ Fill(ft, -1); n = Read(); Q = Read(); for(RG int i = 1; i < n; i++){ RG int u = Read(), v = Read(); Add(u, v); Add(v, u); } cnt = 0; Dfs1(1); Dfs2(1, 1); Build(1, 1, n); while(Q--){ RG int u = Read(), v = Read(); if(u == 1 || v == 1){ puts("0"); continue; } if(dfn[u] > dfn[v]) swap(u, v); ans.u = ans.v = ans.len = 0; if(dfn[u] > 1) Query(1, 1, n, 1, dfn[u] - 1); if(ed[u] + 1 < dfn[v]) Query(1, 1, n, ed[u] + 1, dfn[v] - 1); if(max(ed[v], ed[v]) < n) Query(1, 1, n, max(ed[v], ed[u]) + 1, n); printf("%d\n", ans.len); } return 0; }
相关文章推荐
- (jzoj snow的追寻)线段树维护树的直径
- 【JZOJ 4587】 Snow的追寻
- JZOJ4479【GDOI2016模拟4.26】游戏 线段树维护多条线段的信息
- 用线段树维护树的直径
- JZOJ4774 【GDOI2017模拟9.10】子串 线段树合并维护SAM的fail树信息(CF 666E类似)
- 【线段树维护单调栈】【JZOJ 5402】 God Knows
- 【JZOJ 4587】Snow的追寻
- 51nod 1766 线段树维护树的直径
- 【jzoj4845】【寻找】【线段树】
- CodeChef MONOPOLY 基于Access性质的线段树维护
- [jzoj]1663. 【AHOI2009】维护序列(线段树+乘法加法原理)
- JZOJ 4898 人生的价值(线段树、扫描线)
- [Noi2016]区间[离散化+线段树维护+决策单调性]
- HDU3564 --- Another LIS (线段树维护最值问题)
- HDU 5997 rausen loves cakes (线段树区间维护,启发式区间合并)
- 区间MEX 线段树维护mex数组
- bzoj 2402 陶陶的难题II 01分数规划 树链剖分 线段树维护凸包
- BZOJ 1099([POI2007]树Drz-9次线段树&分类讨论+线段树与插入顺序维护2个参数)
- (1798: [Ahoi2009]Seq 维护序列seq)<线段树乘法操作>
- 【P2023】[AHOI2009]维护序列 线段树