树剖维护,注意方向(\(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