1、HDU 5052 Yaoge’s maximum profit
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>
using namespace std;
#define REP(i, n) for (int i = 0; i < (n); ++i)
#define lson low, mid, _id<<1
#define rson mid+1, high, _id<<1|1
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;
const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 5e4 + 10;
int T, N, Q, X, Y, Z, edge, id_count;
int W[maxn], depth[maxn], son[maxn], top[maxn], size[maxn], father[maxn], id[maxn], key[maxn];
int head[maxn], Next[2*maxn], to[2*maxn];
ll lans[4*maxn], rans[4*maxn], lazy[4*maxn], Max[4*maxn], Min[4*maxn];
void Init(void);
void add_edge(int u, int v);
void dfs_first(int u, int _father, int _depth);
void dfs_second(int u, int _top);
void build(int low, int high, int _id);
void push_up(int _id);
void update(int Left, int Right, ll val, int low, int high, int _id);
void push_down(int _id);
void Update(int u, int v, ll val);
ll slove(int u, int v);
ll query(int Left, int Right, int is_left, ll& max_price, ll& min_price, int low, int high, int _id);
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
scanf("%d", &T);
while (T--) {
scanf("%d", &N);
Init();
for (int i = 1; i <= N; ++i) {
scanf("%d", &W[i]);
}
for (int i = 1; i < N; ++i) {
scanf("%d %d", &X, &Y);
add_edge(X, Y), add_edge(Y, X);
}
dfs_first(1, 0, 1);
dfs_second(1, 1);
build(1, N, 1);
scanf("%d", &Q);
while (Q--) {
scanf("%d %d %d", &X, &Y, &Z);
printf("%I64d\n", slove(X, Y));
Update(X, Y, Z);
}
}
return 0;
}
ll slove(int u, int v)
{
ll ans = 0, max_now_left, min_now_left, max_now_right, min_now_right;
ll max_pre_left = 0, min_pre_left = Max[1], max_pre_right = 0, min_pre_right = Max[1];
while (top[u] != top[v]) {
if (depth[top[u]] > depth[top[v]]) {
ans = max(ans, query(id[top[u]], id[u], 1, max_now_left, min_now_left, 1, N, 1));
ans = max(ans, max_now_left - min_pre_left);
ans = max(ans, max_pre_right - min_now_left);
max_pre_left = max(max_pre_left, max_now_left);
min_pre_left = min(min_pre_left, min_now_left);
u = father[top[u]];
} else {
ans = max(ans, query(id[top[v]], id[v], 0, max_now_right, min_now_right, 1, N, 1));
ans = max(ans, max_pre_right - min_now_right);
ans = max(ans, max_now_right - min_pre_left);
max_pre_right = max(max_pre_right, max_now_right);
min_pre_right = min(min_pre_right, min_now_right);
v = father[top[v]];
}
}
if (depth[u] > depth[v]) {
ans = max(ans, query(id[v], id[u], 1, max_now_left, min_now_left, 1, N, 1));
ans = max(ans, max_now_left - min_pre_left);
min_pre_left = min(min_pre_left, min_now_left);
ans = max(ans, max_pre_right - min_pre_left);
} else {
ans = max(ans, query(id[u], id[v], 0, max_now_right, min_now_right, 1, N, 1));
ans = max(ans, max_pre_right - min_now_right);
max_pre_right = max(max_pre_right, max_now_right);
ans = max(ans, max_pre_right - min_pre_left);
}
return ans;
}
ll query(int Left, int Right, int is_left, ll& max_price, ll& min_price, int low, int high, int _id)
{
if (low == Left && high == Right) {
max_price = Max[_id], min_price = Min[_id];
if (is_left) {
return lans[_id];
} else {
return rans[_id];
}
}
push_down(_id);
int mid = (low + high) >> 1;
if (Right <= mid) {
return query(Left, Right, is_left, max_price, min_price, lson);
} else if (Left > mid) {
return query(Left, Right, is_left, max_price, min_price, rson);
} else {
ll ans_t, max_left, max_right, min_left, min_right;
ll ans = max(query(Left, mid, is_left, max_left, min_left, lson), query(mid+1, Right, is_left, max_right, min_right, rson));
if (is_left) {
ans_t = max_left - min_right;
} else {
ans_t = max_right - min_left;
}
max_price = max(max_left, max_right), min_price = min(min_left, min_right);
ans_t = max(ans_t, 0ll), ans = max(ans, ans_t);
return ans;
}
}
void Update(int u, int v, ll val)
{
while (top[u] != top[v]) {
if (depth[top[u]] < depth[top[v]]) {
swap(u, v);
}
update(id[top[u]], id[u], val, 1, N, 1);
u = father[top[u]];
}
if (depth[u] > depth[v]) {
swap(u, v);
}
update(id[u], id[v], val, 1, N, 1);
}
void update(int Left, int Right, ll val, int low, int high, int _id)
{
if (low == Left && high == Right) {
Max[_id] += val, Min[_id] += val, lazy[_id] += val;
return;
}
push_down(_id);
int mid = (low + high) >> 1;
if (Right <= mid) {
update(Left, Right, val, lson);
} else if (Left > mid) {
update(Left, Right, val, rson);
} else {
update(Left, mid, val, lson), update(mid+1, Right, val, rson);
}
push_up(_id);
}
void push_down(int _id)
{
if (lazy[_id]) {
Max[_id<<1] += lazy[_id], Min[_id<<1] += lazy[_id], lazy[_id<<1] += lazy[_id];
Max[_id<<1|1] += lazy[_id], Min[_id<<1|1] += lazy[_id], lazy[_id<<1|1] += lazy[_id];
lazy[_id] = 0;
}
}
void build(int low, int high, int _id)
{
lazy[_id] = lans[_id] = rans[_id] = 0;
if (low == high) {
Max[_id] = Min[_id] = W[key[low]];
return;
}
int mid = (low + high) >> 1;
build(lson), build(rson);
push_up(_id);
}
void push_up(int _id)
{
Max[_id] = max(Max[_id<<1], Max[_id<<1|1]), Min[_id] = min(Min[_id<<1], Min[_id<<1|1]);
lans[_id] = max(Max[_id<<1] - Min[_id<<1|1], max(lans[_id<<1], lans[_id<<1|1]));
rans[_id] = max(Max[_id<<1|1] - Min[_id<<1], max(rans[_id<<1], rans[_id<<1|1]));
if (lans[_id] < 0) {
lans[_id] = 0;
}
if (rans[_id] < 0) {
rans[_id] = 0;
}
}
void dfs_second(int u, int _top)
{
top[u] = _top;
id[u] = ++id_count;
key[id[u]] = u;
if (son[u] == -1) {
return;
}
dfs_second(son[u], _top);
for (int i = head[u]; ~i; i = Next[i]) {
int v = to[i];
if (v != son[u] && v != father[u]) {
dfs_second(v, v);
}
}
}
void dfs_first(int u, int _father, int _depth)
{
depth[u] = _depth, father[u] = _father, size[u] = 1;
for (int i = head[u]; ~i; i = Next[i]) {
int v = to[i];
if (v != _father) {
dfs_first(v, u, _depth+1);
size[u] += size[v];
if (son[u] == -1 || size[v] > size[son[u]]) {
son[u] = v;
}
}
}
}
void add_edge(int u, int v)
{
to[edge] = v, Next[edge] = head[u], head[u] = edge++;
}
void Init(void)
{
memset(head, -1, sizeof(head));
memset(son, -1, sizeof(son));
edge = id_count = 0;
}