洛谷P4315
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 50;
int fa[maxn], dep[maxn], size[maxn], son[maxn], top[maxn], dfn[maxn], rid[maxn], cnt = 0;
ll val[maxn];
vector<int> g[maxn];
struct node {
int l, r;
ll lazy, val, tag;
}t[maxn * 4];
void dfs1(int u, int f)
{
fa[u] = f;
dep[u] = dep[f] + 1;
size[u] = 1;
for (int i = 0; i < g[u].size(); i++)
{
int v = g[u][i];
if(v != f) {
dfs1(v, u);
size[u] += size[v];
if(size[v] > size[son[u]]) son[u] = v;
}
}
}
void dfs2(int now, int fir)
{
cnt++;
top[now] = fir;
dfn[now] = cnt;
rid[dfn[now]] = now;
if(!son[now]) return;
dfs2(son[now], fir);
for (int i = 0; i < g[now].size(); i++)
{
int v = g[now][i];
if(v != fa[now] && v != son[now])
dfs2(v, v);
}
}
void pushup(int n)
{
t[n].val = max(t[n<<1].val, t[n<<1|1].val);
}
void pushdown(int n)
{
int l = t[n].l, r = t[n].r;
if(l == r) return ;
int mid = (l + r) >> 1;
if(t[n].tag != -1) {
t[n<<1].tag = t[n<<1|1].tag = t[n].tag;
t[n<<1].val = t[n<<1|1].val = t[n].tag;
t[n<<1].lazy = t[n<<1|1].lazy = 0;
t[n].tag = -1;
}
if(t[n].lazy)
{
t[n<<1].lazy += t[n].lazy;
t[n<<1|1].lazy += t[n].lazy;
t[n<<1].val += t[n].lazy;
t[n<<1|1].val += t[n].lazy;
t[n].lazy = 0;
}
}
void build(int n, int l, int r)
{
t[n].l = l;
t[n].r = r;
t[n].lazy = 0;
t[n].tag = -1;
if(l == r) {
t[n].val = val[rid[l]];
return;
}
int mid = (l + r) >> 1;
build(n<<1, l, mid);
build(n<<1|1, mid + 1, r);
pushup(n);
}
void update(int n, int L, int R, ll val, int op)
{
int l = t[n].l, r = t[n].r;
if(L <= l && R >= r) {
if(op == 1) {
t[n].lazy += val;
t[n].val += val;
}
else {
t[n].val = val;
t[n].tag = val;
t[n].lazy = 0;
}
return;
}
pushdown(n);
int mid = (l + r)>>1;
if(L <= mid) update(n<<1, L, R, val, op);
if(R > mid) update(n<<1|1, L, R, val, op);
pushup(n);
}
ll query(int n, int L, int R)
{
int l = t[n].l, r = t[n].r;
if(L <= l && R >= r) return t[n].val;
pushdown(n);
int mid = (l + r) >>1;
ll ans = 0;
if(L <= mid) ans = max(ans, query(n<<1, L, R));
if(R > mid) ans = max(ans, query(n<<1|1, L, R));
pushup(n);
return ans;
}
void subtreechange(int x, int val, int op)
{
update(1, dfn[x], dfn[x] + size[x] - 1, val, op);
}
ll subtreequery(int x)
{
return query(1, dfn[x], dfn[x] + size[x] - 1);
}
void linkchange(int x, int y, int z, int op)
{
while (top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]])
swap(x, y);
update(1, dfn[top[x]], dfn[x], z, op);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
if(dfn[x] + 1 <= dfn[y]) update(1, dfn[x] + 1, dfn[y], z, op);
}
ll linkquery(int x, int y)
{
ll ret = 0;
while (top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]]) swap(x, y);
ret = max(ret, query(1, dfn[top[x]], dfn[x]));
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
if(dfn[x] + 1 <= dfn[y]) ret = max(ret, query(1, dfn[x] + 1, dfn[y]));
return ret;
}
struct linex {
int x, y, z;
}line[maxn];
int main()
{
int n;
scanf("%d", &n);
for (int i = 1; i <= n - 1; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
g[u].push_back(v);
g[v].push_back(u);
line[i].x = u; line[i].y = v; line[i].z = w;
}
dfs1(1, 1);
for (int i = 1; i <= n - 1; i++)
val[fa[line[i].x] == line[i].y ? line[i].x : line[i].y] = line[i].z;
dfs2(1, 0);
build(1, 1, n);
char s[20];
while (1)
{
scanf("%s", s);
int u, v, w;
if(s[1] == 't') break;
if(s[1] == 'a') {
scanf("%d%d",&u, &v);
printf("%lld\n", linkquery(u, v));
}
if(s[1] == 'o') {
scanf("%d%d%d", &u, &v, &w);
linkchange(u, v, w, 2);
}
if(s[1] == 'd') {
scanf("%d%d%d", &u, &v, &w);
linkchange(u, v, w, 1);
}
if(s[1] == 'h') {
scanf("%d%d", &u, &w);
int z = fa[line[u].x] == line[u].y ? line[u].x : line[u].y;
update(1, dfn[z], dfn[z], w, 2);
}
}
return 0;
}