vector< int > adj[maxn]; int up[maxn][maxlg], dep[maxn]; int diff[maxn], ans[maxn]; // diff: 差分数组, ans: 最终统计值 int n, m;
// 1. LCA 预处理 voiddfs_lca( int u, int p ) { dep[u] = dep[p] + 1, up[u][0] = p; for( int i = 1; i < maxlg; ++ i ) up[u][i] = up[up[u][i - 1]][i - 1]; for( int v : adj[u] ) if( v != p ) dfs_lca( v, u ); }
intget_lca( int u, int v ) { if( dep[u] < dep[v] ) swap( u, v ); int dif = dep[u] - dep[v]; for( int i = maxlg - 1; i >= 0; -- i ) if( ( diff >> i ) & 1 ) u = up[u][i]; if( u == v ) return u; for( int i = maxlg - 1; i >= 0; -- i ) if( up[u][i] != up[v][i] ) u = up[u][i], v = up[v][i]; return up[u][0]; }
// 2.1 修改:点差分 voidmodify_node( int u, int v, int w ) { int lca = get_lca( u, v ); diff[u] += w; diff[v] += w; diff[lca] -= w; if( up[lca][0] != 0 ) diff[up[lca][0]] -= w; // 注意判根 }
// 2.2 修改:边差分 voidmodify_edge( int u, int v, int w ) { int lca = get_lca( u, v ); diff[u] += w; diff[v] += w; diff[lca] -= 2 * w; }
// 3. 统计:子树前缀和 (自底向上) voiddfs_sum( int u, int p ) { ans[u] = diff[u]; for( int v : adj[u] ) { if( v == p ) continue; dfs_sum( v, u ); ans[u] += ans[v]; // 累加子树贡献 } }