Description
有n座城市,由n-1条路相连通,使得任意两座城市之间可达。每条路有过路费,要交过路费才能通过。每条路的过路费经常会更新,现问你,当前情况下,从城市a到城市b最少要花多少过路费。
Input
有多组样例,每组样例第一行输入两个正整数n,m(2 <= n<=50000,1<=m <= 50000),接下来n-1行,每行3个正整数a b c,(1 <= a,b <= n , a != b , 1 <= c <= 1000000000).数据保证给的路使得任意两座城市互相可达。接下来输入m行,表示m个操作,操作有两种:一. 0 a b,表示更新第a条路的过路费为b,1 <= a <= n-1 ; 二. 1 a b , 表示询问a到b最少要花多少过路费。
Output
对于每个询问,输出一行,表示最少要花的过路费。
Sample Input
2 3 1 2 1 1 1 2 0 1 2 1 2 1
Sample Output
12
同POJ2763,树链剖分+树状数组
#include<cstdio> #include<algorithm> using namespace std; #define rep(i,j,k) for(int i=j;i<=k;i++) #define loop(i,j,k) for (int i=j;i!=-1;i=k[i]) #define inone(x) scanf("%d",&x) #define intwo(x,y) scanf("%d%d",&x,&y) const int low(int x) { return x&-x; } const int N = 2e5 + 10; int n, m, x, y, z; int ft[N], nt[N], u[N], v[N], sz = 0; int ct[N], mx[N], fa[N], dep[N]; int top[N], g[N], G[N], a[N]; long long f[N]; void add(int x, int y) { for (int i = x; i <= n; i += low(i)) f[i] += y; } long long sum(int x) { long long res = 0; for (int i = x; i; i -= low(i)) res += f[i]; return res; } void dfs(int x, int f) { dep[x] = dep[f] + 1; fa[x] = f; ct[x] = 1; mx[x] = 0; loop(i, ft[x], nt) { if (u[i] == f) continue; dfs(u[i], x); ct[x] += ct[u[i]]; if (ct[u[i]] > ct[mx[x]]) mx[x] = u[i]; } } void Dfs(int x, int t) { top[x] = !t ? x : top[fa[x]]; g[x] = ++sz; if (mx[x]) Dfs(mx[x], 1); loop(i, ft[x], nt) { if (u[i] == fa[x]) continue; if (u[i] == mx[x]) { G[v[i]] = g[u[i]]; continue; } Dfs(u[i], 0); G[v[i]] = g[u[i]]; } } long long get(int x, int y) { long long res = 0; while (top[x] != top[y]) { if (dep[top[x]] < dep[top[y]]) swap(x, y); res += sum(g[x]) - sum(g[top[x]] - 1); x = fa[top[x]]; } if (dep[x] > dep[y]) swap(x, y); return res + sum(g[y]) - sum(g[x]); } int main() { while (scanf("%d%d", &n, &m) != EOF) { dep[0] = ct[0] = sz = 0; rep(i, 1, n) ft[i] = -1, f[i] = 0; rep(i, 1, n - 1) { intwo(x, y); inone(a[i]); u[sz] = y; v[sz] = i; nt[sz] = ft[x]; ft[x] = sz++; u[sz] = x; v[sz] = i; nt[sz] = ft[y]; ft[y] = sz++; } dfs(1, 0); Dfs(1, sz = 0); rep(i, 1, n - 1) add(G[i], a[i]); while (m--) { inone(x); intwo(y, z); if (x) { printf("%lld\n", get(y, z)); } else { add(G[y], -a[y]); add(G[y], a[y] = z); } } } return 0; }