洛谷 2590 树的统计
这个题主要是一些线段树和树剖的基本操作,这里不再赘述(反正大家都会)
不过还是提几个小细节:
1. 注意点的树上编号和新编号的转换和使用(特别是单点修改时)。
2. 点权有负数,maxans的最小值要赋到-30001。
AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 500030; int n, cnt, nid; int f[MAXN]; int top[MAXN]; int son[MAXN]; int lid[MAXN]; int dep[MAXN]; int siz[MAXN]; int val[MAXN]; int nva[MAXN]; int faz[MAXN]; string s; int read() { int x = 0; int k = 1; char c = getchar(); while (!isdigit(c)) if (c == '-') k = -1, c = getchar(); else c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); return k * x; } struct edge { int w; int u; int v; int next; }e[MAXN<<1]; void addedge(int x, int y) { ++cnt; e[cnt].u = x; e[cnt].v = y; e[cnt].next = f[x]; f[x] = cnt; } void dfs1(int u, int father, int depth) { dep[u] = depth; faz[u] = father; siz[u] = 1; for (int i = f[u]; i != -1; i = e[i].next) { int to = e[i].v; if (to == father) continue; dfs1(to, u, depth + 1); siz[u] += siz[to]; if (siz[to] > siz[son[u]] || son[u] == -1) son[u] = to; } } void dfs2(int u, int h) { ++nid; lid[u] = nid; nva[nid] = val[u]; top[u] = h; if (son[u] == -1) return; dfs2(son[u], h); for (int i = f[u]; i != -1; i = e[i].next) { int to = e[i].v; if (!lid[to]) dfs2(to, to); } } // Segmenttree #define ls u << 1 #define rs u << 1 | 1 struct segtree { int l; int r; int w; int b; int siz; }t[MAXN << 2]; void update(int u) { t[u].w = t[ls].w + t[rs].w; t[u].b = max(t[ls].b, t[rs].b); } void build(int u, int l, int r) { t[u].l = l; t[u].r = r; t[u].siz = r - l + 1; if (l == r) { t[u].w = nva[l]; t[u].b = nva[l]; return; } int mid = (l + r) >> 1; build(ls, l, mid); build(rs, mid + 1, r); update(u); } void change(int u, int ll, int c) { if (t[u].l == t[u].r && t[u].l == ll) { t[u].w = c; t[u].b = c; return; } int mid = (t[u].l + t[u].r) >> 1; if (ll <= mid) change(ls, ll, c); if (ll > mid) change(rs, ll, c); update(u); } int max_(int u, int l, int r) { if (t[u].l >= l && t[u].r <= r) return t[u].b; int mid = (t[u].l + t[u].r) >> 1; int ans = -1000000000; if (l <= mid) ans = max(ans, max_(ls, l, r)); if (r > mid) ans = max(ans, max_(rs, l, r)); return ans; } int sum_(int u, int l, int r) { if (t[u].l >= l && t[u].r <= r) return t[u].w; int mid = (t[u].l + t[u].r) >> 1; int ans = 0; if (l <= mid) ans += sum_(ls, l, r); if (r > mid) ans += sum_(rs, l, r); return ans; } //sparate int tsum_(int x, int y) { int ans = 0; while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); ans += sum_(1, lid[top[x]], lid[x]); x = faz[top[x]]; } if (dep[x] > dep[y]) swap(x, y); ans += sum_(1, lid[x], lid[y]); return ans; } int tmax_(int x, int y) { int ans = -10000000; while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); ans = max(ans, max_(1, lid[top[x]], lid[x])); x = faz[top[x]]; } if (dep[x] > dep[y]) swap(x, y); ans = max(ans, max_(1, lid[x], lid[y])); return ans; } //main int main() { memset(son, -1, sizeof(son)); memset(f, -1, sizeof(f)); n = read(); for (int i = 1; i < n; ++i) { int x, y; x = read(); y = read(); addedge(x, y); addedge(y, x); } for (int i = 1; i <= n; ++i) val[i] = read(); dfs1(1, 0, 1); dfs2(1, 1); build(1, 1, n); int q = read(); while (q--) { cin >> s; int x = read(); int y = read(); if (s[1] == 'H') change(1, lid[x], y); else if (s[1] == 'S') printf("%d\n", tsum_(x, y)); else if (s[1] == 'M') printf("%d\n", tmax_(x, y)); } }