树剖维护,注意方向(\(a \rightarrow b \neq b \rightarrow a\))。
#include <cstdio> #define UP_TO_DOWN 0 #define DOWN_TO_UP 1 typedef bool qtype; const int MAXN = 5e4 + 19; class Query{ private: int min, max, sub; public: Query(){ min = 0x3f3f3f3f, max = -0x3f3f3f3f, sub = 0; } Query(int __min, int __max, int __sub){ min = __min, max = __max, sub = __sub; } Query operator^=(const Query& b){ sub = sub > b.sub ? sub : b.sub; sub = sub > (b.max - min) ? sub : (b.max - min); min = min < b.min ? min : b.min; max = max > b.max ? max : b.max; } Query operator^(const Query& b)const{ Query res = *this; res ^= b; return res; } int data(void){ return sub; } }; class SegmentTree{ private: struct Node{ int l, r; int min, max, subl, subr; int tag; }tr[MAXN << 2]; int __min(const int& a, const int& b){ return a < b ? a : b; } int __max(const int& a, const int& b){ return a > b ? a : b; } void push_down(int node){ if(tr[node].tag){ tr[node << 1].min += tr[node].tag; tr[node << 1].max += tr[node].tag; tr[node << 1].tag += tr[node].tag; tr[node << 1 | 1].min += tr[node].tag; tr[node << 1 | 1].max += tr[node].tag; tr[node << 1 | 1].tag += tr[node].tag; tr[node].tag = 0; } } void push_up(int node){ tr[node].min = __min(tr[node << 1].min, tr[node << 1 | 1].min); tr[node].max = __max(tr[node << 1].max, tr[node << 1 | 1].max); tr[node].subl = tr[node << 1 | 1].max - tr[node << 1].min; tr[node].subl = __max(tr[node].subl, tr[node << 1].subl); tr[node].subl = __max(tr[node].subl, tr[node << 1 | 1].subl); tr[node].subr = tr[node << 1].max - tr[node << 1 | 1].min; tr[node].subr = __max(tr[node].subr, tr[node << 1].subr); tr[node].subr = __max(tr[node].subr, tr[node << 1 | 1].subr); } void build(int node, int l, int r, int *w){ tr[node].l = l, tr[node].r = r; if(l == r){ tr[node].max = w[l]; tr[node].min = w[l]; tr[node].subl = 0; tr[node].subr = 0; return; } int mid = (l + r) >> 1; build(node << 1, l, mid, w); build(node << 1 | 1, mid + 1, r, w); push_up(node); } void modify(int node, int l, int r, const int& val){ if(tr[node].l >= l && tr[node].r <= r){ tr[node].min += val; tr[node].max += val; tr[node].tag += val; return; } push_down(node); int mid = (tr[node].l + tr[node].r) >> 1; if(l <= mid) modify(node << 1, l, r, val); if(r > mid) modify(node << 1 | 1, l, r, val); push_up(node); } Query query(int node, int l, int r, qtype q){ if(tr[node].l >= l && tr[node].r <= r){ int sub; if(q == UP_TO_DOWN) sub = tr[node].subl; else if(q == DOWN_TO_UP) sub = tr[node].subr; return Query(tr[node].min, tr[node].max, sub); } push_down(node); Query res; int mid = (tr[node].l + tr[node].r) >> 1; if(l <= mid){ if(q == UP_TO_DOWN) res = res ^ query(node << 1, l, r, q); else if(q == DOWN_TO_UP) res = query(node << 1, l, r, q) ^ res; } if(r > mid){ if(q == UP_TO_DOWN) res = res ^ query(node << 1 | 1, l, r, q); else if(q == DOWN_TO_UP) res = query(node << 1 | 1, l, r, q) ^ res; } return res; } public: void build(int l, int r, int *w){ build(1, l, r, w); } void modify(int l, int r, const int& val){ modify(1, l, r, val); } Query query(int l, int r, qtype q){ return query(1, l, r, q); } }myTree; struct Edge{ int to, next; }edge[MAXN << 1]; int cnt, head[MAXN]; inline void add(int from, int to){ edge[++cnt].to = to; edge[cnt].next = head[from]; head[from] = cnt; } int n, q, p[MAXN], z[MAXN]; int ind; int fa[MAXN], son[MAXN], dep[MAXN], size[MAXN], dfn[MAXN], top[MAXN]; void dfs1(int node, int f){ fa[node] = f, dep[node] = dep[f] + 1, size[node] = 1; int max = 0; for(int i = head[node]; i; i = edge[i].next) if(edge[i].to != f){ dfs1(edge[i].to, node); size[node] += size[edge[i].to]; if(size[edge[i].to] > max) max = size[edge[i].to], son[node] = edge[i].to; } } void dfs2(int node, int f, int t){ dfn[node] = ++ind, top[node] = t; if(son[node]) dfs2(son[node], node, t); for(int i = head[node]; i; i = edge[i].next) if(edge[i].to != f && edge[i].to != son[node]) dfs2(edge[i].to, node, edge[i].to); } int query(int x, int y, const int& val){ Query l, r; while(top[x] != top[y]){ if(dep[top[x]] > dep[top[y]]) myTree.modify(dfn[top[x]], dfn[x], val), l = l ^ myTree.query(dfn[top[x]], dfn[x], DOWN_TO_UP), x = fa[top[x]]; else myTree.modify(dfn[top[y]], dfn[y], val), r = myTree.query(dfn[top[y]], dfn[y], UP_TO_DOWN) ^ r, y = fa[top[y]]; } if(dep[x] < dep[y]) myTree.modify(dfn[x], dfn[y], val), l = l ^ myTree.query(dfn[x], dfn[y], UP_TO_DOWN); else myTree.modify(dfn[y], dfn[x], val), r = myTree.query(dfn[y], dfn[x], DOWN_TO_UP) ^ r; return (l ^ r).data(); } int main(){ std::scanf("%d", &n); for(int i = 1; i <= n; ++i) std::scanf("%d", p + i); for(int u, v, i = 1; i < n; ++i){ std::scanf("%d%d", &u, &v); add(u, v); add(v, u); } dfs1(1, 0); dfs2(1, 0, 1); for(int i = 1; i <= n; ++i) z[dfn[i]] = p[i]; myTree.build(1, n, z); std::scanf("%d", &q); for(int a, b, v, i = 1; i <= q; ++i){ std::scanf("%d%d%d", &a, &b, &v); std::printf("%d\n", query(a, b, v)); } return 0; }
来源:https://www.cnblogs.com/natsuka/p/12611833.html