51nod1766 树上的最远点对
欧拉序可以 $O(1)$ 得到两点的 LCA
线段树维护区间直径,两个区间合并时,新的直径的端点肯定是这两个子区间直径的端点。
复杂度 $O(nlogn)$
#include <cstdio> #include <cstring> #include <cctype> #include <algorithm> #include <vector> inline void checkmax(int &a, int b) { if (a < b) a = b; } inline void checkmin(int &a, int b) { if (a > b) a = b; } namespace IO { char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n'; int p, p3 = -1; void read() {} void print() {} inline int getc() { return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++; } inline void flush() { fwrite(buf2, 1, p3 + 1, stdout), p3 = -1; } template <typename T, typename... T2> inline void read(T &x, T2 &... oth) { T f = 1; x = 0; char ch = getc(); while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getc(); } while (isdigit(ch)) { x = x * 10 + ch - 48; ch = getc(); } x *= f; read(oth...); } template <typename T, typename... T2> inline void print(T x, T2... oth) { if (p3 > 1 << 20) flush(); if (x < 0) buf2[++p3] = 45, x = -x; do { a[++p] = x % 10 + 48; } while (x /= 10); do { buf2[++p3] = a[p]; } while (--p); buf2[++p3] = hh; print(oth...); } } // using namespace IO #define read IO::read #define print IO::print #define flush IO::flush #define pii pair<int, int> #define fi first #define se second const int N = 2e5 + 7; const int sz = 20; int n, tol, dfn[N], in[N], out[N], dep[N]; int st[N][sz], lg[N]; std::vector<std::pii> vec[N]; void dfs(int u, int pre = 0) { dfn[++tol] = u; in[u] = tol; for (auto p: vec[u]) { int v = p.fi; if (v == pre) continue; dep[v] = dep[u] + p.se; dfs(v, u); dfn[++tol] = u; } out[u] = tol; } void init() { for (int i = 2, j = 0; i <= tol; i++) lg[i] = ((1 << (j + 1)) == i) ? ++j : j; for (int i = 1; i <= tol; i++) st[i][0] = i; for (int j = 1; (1 << j) <= tol; j++) for (int i = 1; i + (1 << j) - 1 <= tol; i++) st[i][j] = dep[dfn[st[i][j - 1]]] < dep[dfn[st[i + (1 << (j - 1))][j - 1]]] ? st[i][j - 1] : st[i + (1 << (j - 1))][j - 1]; } inline int lca(int u, int v) { int x = in[u], y = in[v]; if (x > y) std::swap(x, y); int logg = lg[y - x + 1]; int lca = (dep[dfn[st[x][logg]]] < dep[dfn[st[y - (1 << logg) + 1][logg]]]) ? dfn[st[x][logg]] : dfn[st[y - (1 << logg) + 1][logg]]; return lca; } inline int getdis(int u, int v) { return dep[u] + dep[v] - 2 * dep[lca(u, v)]; } struct Seg { #define lp p << 1 #define rp p << 1 | 1 int tree[N << 2], p1[N << 2], p2[N << 2]; void pushup(int p) { checkmax(tree[p], tree[lp]); checkmax(tree[p], tree[rp]); int lu = p1[lp], lv = p2[lp], ru = p1[rp], rv = p2[rp]; checkmax(tree[p], getdis(lu, ru)); checkmax(tree[p], getdis(lu, rv)); checkmax(tree[p], getdis(lv, ru)); checkmax(tree[p], getdis(lv, rv)); if (tree[p] == tree[lp]) p1[p] = p1[lp], p2[p] = p2[lp]; else if (tree[p] == tree[rp]) p1[p] = p1[rp], p2[p] = p2[rp]; else if (tree[p] == getdis(lu, ru)) p1[p] = lu, p2[p] = ru; else if (tree[p] == getdis(lu, rv)) p1[p] = lu, p2[p] = rv; else if (tree[p] == getdis(lv, ru)) p1[p] = lv, p2[p] = ru; else p1[p] = lv, p2[p] = rv; } void build(int p, int l, int r) { if (l == r) { p1[p] = p2[p] = l; return; } int mid = l + r >> 1; build(lp, l, mid); build(rp, mid + 1, r); pushup(p); } std::pii query(int p, int l, int r, int x, int y) { if (x <= l && y >= r) return std::pii(p1[p], p2[p]); int mid = l + r >> 1; if (x > mid) return query(rp, mid + 1, r, x, y); if (y <= mid) return query(lp, l, mid, x, y); auto pp = query(lp, l, mid, x, y), qq = query(rp, mid + 1, r, x, y); int len = 0; checkmax(len, getdis(pp.fi, pp.se)); checkmax(len, getdis(qq.fi, qq.se)); checkmax(len, getdis(pp.fi, qq.fi)); checkmax(len, getdis(pp.fi, qq.se)); checkmax(len, getdis(pp.se, qq.fi)); checkmax(len, getdis(pp.se, qq.se)); if (len == getdis(pp.fi, pp.se)) return pp; if (len == getdis(qq.fi, qq.se)) return qq; if (len == getdis(pp.fi, qq.fi)) return std::pii(pp.fi, qq.fi); if (len == getdis(pp.fi, qq.se)) return std::pii(pp.fi, qq.se); if (len == getdis(pp.se, qq.fi)) return std::pii(pp.se, qq.fi); return std::pii(pp.se, qq.se); } } seg; int main() { freopen("in.txt", "r", stdin); read(n); for (int i = 1, u, v, w; i < n; i++) { read(u, v, w); vec[u].push_back(std::pii(v, w)); vec[v].push_back(std::pii(u, w)); } dfs(1, 0); init(); seg.build(1, 1, n); int m; read(m); for (int i = 1, a, b, c, d; i <= m; i++) { read(a, b, c, d); auto p1 = seg.query(1, 1, n, a, b); auto p2 = seg.query(1, 1, n, c, d); int ans = 0; checkmax(ans, getdis(p1.fi, p2.fi)); checkmax(ans, getdis(p1.se, p2.se)); checkmax(ans, getdis(p1.fi, p2.se)); checkmax(ans, getdis(p1.se, p2.fi)); print(ans); } flush(); return 0; }

浙公网安备 33010602011771号