思路:一眼看上去就有点树链刨分的感觉。不过现场时死活就是超时,结果发现long long改成int就过。
首先我们把树正常的刨成线段树,然后线段树结点保存该区间的最大最小值,还有区间最优解,以及区间逆向最优解,懒操作值。根据这几个值就可以解此题目,复杂度是mlog(n)的。
#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
#define N 50004
#define lc (d<<1)
#define rc (d<<1|1)
#define mid (l+r>>1)
struct Tr{
int re, mx, mi, lz, ni;
}tr[N<<2];
struct E{
int v, ne;
E(){}
E(int _v, int _ne):v(_v), ne(_ne){}
}e[N<<1];
int size, head[N], n, m;
int fa[N], tid[N], top[N], dep[N], sun[N], dfn, sid[N];
int val[N], pre[N];
void init() {
size = 0;
memset(tid, -1, sizeof(tid));
memset(head, -1, sizeof(head));
}
void add(int u, int v) {
e[size] = E(v, head[u]);
head[u] = size++;
}
int dfs(int u, int f) {
int mi = 0, v, i, s = u, c = 1, sd = 0;
for (i = head[u];~i;i = e[i].ne) {
v = e[i].v;
if (v == f) continue;
int tm = dfs(v, u);
c += tm;
if (tm > mi) mi = tm, s = v;
}
sun[u] = s;
return c;
}
void dfs1(int u, int f, int d, int Top) {
dep[u] = d, fa[u] = f, top[u] = Top, tid[u] = ++dfn, pre[dfn] = u;
if (tid[sun[u]] == -1) {
dfs1(sun[u], u, d+1, Top);
}
int v, i;
for (i = head[u];~i;i = e[i].ne) {
v = e[i].v;
if (tid[v] != -1) continue;
dfs1(v, u, d+1, v);
}
}
inline void Push(int d) {
tr[d].re = 0;
tr[d].mi = min(tr[lc].mi, tr[rc].mi);
tr[d].mx = max(tr[lc].mx, tr[rc].mx);
tr[d].re = max(tr[d].re, max(tr[lc].re, tr[rc].re));
tr[d].re = max(tr[d].re, tr[rc].mx-tr[lc].mi);
tr[d].ni = 0;
tr[d].ni = max(tr[d].ni, max(tr[lc].ni, tr[rc].ni));
tr[d].ni = max(tr[d].ni, tr[lc].mx-tr[rc].mi);
}
void build(int d, int l, int r) {
tr[d].lz = 0;
if (l == r) {
tr[d].mi = tr[d].mx = val[pre[l]];
tr[d].re = tr[d].ni = 0;
return;
}
build(lc, l, mid), build(rc, mid+1, r);
Push(d);
}
struct Em{
int re, mi, mx;
Em(){}
Em(int _r, int _i, int _x):re(_r), mi(_i), mx(_x){}
Em operator+(Em a) const {
Em tm;
tm.re = max(a.re, re);
tm.mx = max(a.mx, mx);
tm.mi = min(a.mi, mi);
tm.re = max(tm.re, a.mx-mi);
return tm;
}
};
vector<Em>V;
inline void lazy(int d, int l, int r) {
if (tr[d].lz) {
tr[lc].lz += tr[d].lz;
tr[lc].mi += tr[d].lz, tr[lc].mx += tr[d].lz;
tr[rc].lz += tr[d].lz;
tr[rc].mi += tr[d].lz, tr[rc].mx += tr[d].lz;
tr[d].lz = 0;
}
}
Em query(int d, int l, int r, int L, int R, int k, int ad) {
if (l == L && r == R) {
Em tm = Em(k?tr[d].re:tr[d].ni, tr[d].mi, tr[d].mx);
tr[d].lz += ad, tr[d].mi += ad, tr[d].mx += ad;
return tm;
}
lazy(d, l, r);
Em tm;
if (R <= mid) tm = query(lc, l, mid, L, R, k, ad);
else if (L > mid) tm = query(rc, mid+1, r, L, R, k, ad);
else {
Em tl = query(lc, l, mid, L, mid, k, ad);
Em tr = query(rc, mid+1, r, mid+1, R, k, ad);
tm.mi = min(tl.mi, tr.mi);
tm.mx = max(tl.mx, tr.mx);
tm.re = max(tl.re, tr.re);
if (k) {
tm.re = max(tm.re, tr.mx-tl.mi);
}else {
tm.re = max(tm.re, tl.mx-tr.mi);
}
}
Push(d);
return tm;
}
void solve(int u, int v, int k) {
int re = 0;
int i = -1;
V.clear();
Em tm;
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) {
V.push_back(query(1, 1, dfn, tid[top[v]], tid[v], 1, k));
v = fa[top[v]];
}else {
if (i < 0) tm = query(1, 1, dfn, tid[top[u]], tid[u], 0, k);
else tm = tm+query(1, 1, dfn, tid[top[u]], tid[u], 0, k);
i = 0;
u = fa[top[u]];
}
}
int f = 1;
if (tid[u] > tid[v]) swap(u, v), f = 0;
if (i < 0) tm = query(1, 1, dfn, tid[u], tid[v], f, k);
else tm = tm+query(1, 1, dfn, tid[u], tid[v], f, k);
for (i = V.size()-1;i >= 0;i--) {
tm = tm+V[i];
}
re = max(re, tm.re);
printf("%d\n", re);
}
inline int in() {
char c;
int re = 0;
c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') {
re = re*10+c-'0';
c = getchar();
}
return re;
}
int main() {
int T, i, j, u, v, n, m, d;
T = in();
while (T--) {
n = in();//scanf("%d", &n);
init();
for (i = 1;i <= n;i++) val[i] = in();//scanf("%d", &val[i]);
for (i = 1;i < n;i++) {
u = in(), v = in();//scanf("%d%d", &u, &v);
add(u, v), add(v, u);
}
dfn = 0;
dfs(1, 0);
dfs1(1, 0, 1, 1);
build(1, 1, n);
m = in();//scanf("%d", &m);
while (m--) {
u = in(), v = in(), d = in();//'scanf("%d%d%d", &u, &v, &d);
solve(u, v, d);
}
}
}