#include<bits/stdc++.h>
using namespace std;
const int N = 200000 + 10;
const long long inf = 1ll<<60;
const int maxh = 20;
int n, q, a[N*2], b[N*2], c[N*2], rev[N], st[N], ed[N], idfn, head[N], cnt;
long long bit[N], dist[N];
struct Edge {
int nxt, to, val;
} e[N * 2];
void addedge(int u, int v, int w) {
e[++cnt].nxt = head[u];
e[cnt].to = v;
e[cnt].val = w;
head[u] = cnt;
}
// Segment Tree
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int MAXN = 200000 + 10;
long long add[MAXN<<2], mn[MAXN<<2];
void PushUp(int rt) { mn[rt] = min(mn[rt<<1], mn[rt<<1|1]); }
void PushDown(int rt, int m) {
if(add[rt]) {
add[rt<<1] += add[rt];
add[rt<<1|1] += add[rt];
mn[rt<<1] += add[rt];
mn[rt<<1|1] += add[rt];
add[rt] = 0;
}
}
void build(int l, int r, int rt) {
add[rt] = 0;
if(l == r) {
mn[rt] = dist[l];
return;
}
int m = (l+r)>>1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int L, int R, long long w, int l, int r, int rt) {
if(L>R) return;
if(L <= l && r <= R) {
add[rt] += w;
mn[rt] += w;
return;
}
PushDown(rt, r-l+1);
int m = (l+r) >> 1;
if(L <= m) update(L, R, w, lson);
if(m < R) update(L, R, w, rson);
PushUp(rt);
}
long long query(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) return mn[rt];
PushDown(rt, r-l+1);
int m = (l+r) >> 1;
long long ret = inf;
if(L <= m) ret = min(ret, query(L, R, lson));
if(m < R) ret = min(ret, query(L, R, rson));
return ret;
}
// LCA
int dep[N];
int anc[N][20];
void dfs(int rt) {
static int Stack[N];
int top = 0;
dep[rt] = 1;
for(int i=0;i<maxh;i++)
anc[rt][i] = rt;
Stack[++top] = rt;
while(top) {
int x = Stack[top];
if(x != rt) {
for(int i=1, y;i<maxh;i++)
y = anc[x][i-1], anc[x][i] = anc[y][i-1];
}
for(int &i=head[x];i;i=e[i].nxt) {
int y = e[i].to;
if(y != anc[x][0]) {
dep[y] = dep[x] + 1;
anc[y][0] = x;
Stack[++top] = y;
}
}
while(top && head[Stack[top]] == 0) top--;
}
}
void swim(int &x, int H) {
for(int i=0;H;i++) {
if(H & 1) x = anc[x][i];
H /= 2;
}
}
int lca(int x, int y) {
int i;
if(dep[x] > dep[y]) swap(x, y);
swim(y, dep[y]-dep[x]);
if(x == y) return x;
for(;;) {
for(i=0;anc[x][i] != anc[y][i];i++);
if(i == 0) return anc[x][0];
x = anc[x][i-1];
y = anc[y][i-1];
}
return -1;
}
void getDfn(int rt, int fa, long long w)
{
st[rt] = ++idfn;
dist[st[rt]] = w + rev[rt];
for(int i=head[rt];i;i=e[i].nxt) {
if(e[i].to == fa) continue;
getDfn(e[i].to, rt, w+e[i].val);
}
ed[rt] = idfn;
}
int main(){
//freopen("in.txt","r",stdin);
scanf("%d %d", &n, &q);
for(int i=1;i<=2*n-2;i++) {
scanf("%d %d %d", &a[i], &b[i], &c[i]);
if(i < n) addedge(a[i], b[i], c[i]), addedge(b[i], a[i], c[i]);
else rev[ a[i] ] = c[i];
}
getDfn(1, 0, 0);
dfs(1);
build(1, n, 1);
for(int op, i, w, u, v;q--;) {
scanf("%d", &op);
if(op == 1) {
scanf("%d %d", &i, &w);
if(i >= n) {
update(st[ a[i] ], st[ a[i] ], w-rev[ a[i] ], 1, n, 1);
rev[ a[i] ] = w;
} else {
update(st[ b[i] ], ed[ b[i] ], w-c[i], 1, n, 1);
c[i] = w;
}
} else {
scanf("%d %d", &u, &v);
if(lca(u, v) == u) {
long long du = query(st[u], st[u], 1, n, 1) - rev[u];
long long dv = query(st[v], st[v], 1, n, 1) - rev[v];
printf("%lld\n", dv - du);
} else {
long long mnDist = query(st[u], ed[u], 1, n, 1) - query(st[u], st[u], 1, n, 1) + rev[u];
long long dv = query(st[v], st[v], 1, n, 1) - rev[v];
printf("%lld\n", mnDist + dv);
}
}
}
}
总结
难度挺大的一题