1. 程式人生 > >51nod1766 樹上的最遠點對 線段樹維護直徑

51nod1766 樹上的最遠點對 線段樹維護直徑

Description n個點被n-1條邊連線成了一顆樹,給出aba~bcdc~d兩個區間,表示點的標號請你求出兩個區間內各選一點之間的最大距離,即你需要求出maxdis(i,j)a<=i<=b,c<=j<=dmax{dis(i,j) |a<=i<=b,c<=j<=d}

Sample Input 5 1 2 1 2 3 2 1 4 3 4 5 4 1 2 3 4 5

Sample Output 10

線段樹維護直徑,存個板子。。。

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long LL;
int read() {
	int s = 0, f = 1; char ch = getchar();
	while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
	while(ch >=
'0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar(); return s * f; } struct edge { int x, y, c, next; } e[210000]; int len, last[110000]; struct tnode { int lc, rc, l, r, x1, x2; } t[210000]; int cnt; int id, ll[110000], rr[110000], st[20][210000]; int dep[110000], fa[20][110000]; LL dis[110000]; void ins(int x, int y,
int c) { e[++len].x = x, e[len].y = y, e[len].c = c; e[len].next = last[x], last[x] = len; } int _min(int x, int y) {return dep[x] < dep[y] ? x : y;} LL LCA(int x, int y) { if(ll[x] > ll[y]) swap(x, y); int l = ll[x], r = ll[y]; int h = log2(r - l + 1); int lca = _min(st[h][l], st[h][r - (1 << h) + 1]); return dis[x] + dis[y] - dis[lca] * 2LL; } tnode _max(tnode x, tnode y) { tnode now; LL ans = LCA(x.x1, x.x2); now.x1 = x.x1, now.x2 = x.x2; LL u = LCA(y.x1, y.x2); if(u > ans) now.x1 = y.x1, now.x2 = y.x2, ans = u; u = LCA(x.x1, y.x1); if(u > ans) now.x1 = x.x1, now.x2 = y.x1, ans = u; u = LCA(x.x1, y.x2); if(u > ans) now.x1 = x.x1, now.x2 = y.x2, ans = u; u = LCA(x.x2, y.x1); if(u > ans) now.x1 = x.x2, now.x2 = y.x1, ans = u; u = LCA(x.x2, y.x2); if(u > ans) now.x1 = x.x2, now.x2 = y.x2; return now; } void bt(int l, int r) { int now = ++cnt; t[now].l = l, t[now].r = r; t[now].lc = t[now].rc = -1; if(l < r) { int mid = (l + r) / 2; int lc = cnt + 1; bt(l, mid); int rc = cnt + 1; bt(mid + 1, r); t[now] = _max(t[lc], t[rc]); t[now].l = l, t[now].r = r; t[now].lc = lc, t[now].rc = rc; } else t[now].x1 = t[now].x2 = l; } tnode query(int now, int l, int r) { if(t[now].l == l && t[now].r == r) return t[now]; int mid = (t[now].l + t[now].r) / 2; int lc = t[now].lc, rc = t[now].rc; if(r <= mid) return query(t[now].lc, l, r); else if(l > mid) return query(t[now].rc, l, r); else return _max(query(t[now].lc, l, mid), query(t[now].rc, mid + 1, r)); } void dfs(int x) { ll[x] = ++id; st[0][id] = x; for(int i = 1; (1 << i) <= dep[x]; i++) fa[i][x] = fa[i - 1][fa[i - 1][x]]; for(int k = last[x]; k; k = e[k].next) { int y = e[k].y; if(y != fa[0][x]) { fa[0][y] = x, dis[y] = dis[x] + e[k].c, dep[y] = dep[x] + 1, dfs(y); st[0][++id] = x; } } } int main() { int n = read(); for(int i = 1; i < n; i++) { int x = read(), y = read(), c = read(); ins(x, y, c), ins(y, x, c); } dfs(1); for(int i = 1; i <= 19; i++) { for(int j = 1; j + (1 << i) - 1 <= id; j++) { st[i][j] = _min(st[i - 1][j], st[i - 1][j + (1 << i - 1)]); } } bt(1, n); int m = read(); for(int i = 1; i <= m; i++) { int l1 = read(), r1 = read(), l2 = read(), r2 = read(); tnode h1 = query(1, l1, r1), h2 = query(1, l2, r2); LL ans = 0; LL u = LCA(h1.x1, h2.x1); if(u > ans) ans = u; u = LCA(h1.x1, h2.x2); if(u > ans) ans = u; u = LCA(h1.x2, h2.x1); if(u > ans) ans = u; u = LCA(h1.x2, h2.x2); if(u > ans) ans = u; printf("%lld\n", ans); } return 0; }