51nod1766 樹上的最遠點對 線段樹維護直徑
阿新 • • 發佈:2018-12-16
Description n個點被n-1條邊連線成了一顆樹,給出和兩個區間,表示點的標號請你求出兩個區間內各選一點之間的最大距離,即你需要求出
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;
}