经典题,动态修改树上的边权,询问树上2点距离。LCA + 树状数组。
len[i] 表示 点 i 到根距离
容易看出,修改一条边必然使一棵子树所有点的 len 增加相同的数,由此问题迎刃而解。
Time Limit: 4000MS | Memory Limit: 65536K | |
Total Submissions: 6554 | Accepted: 1680 |
Description
Input
Output
Sample Input
3 3 1 1 2 1 2 3 2 0 2 1 2 3 0 3
Sample Output
1 3
Source
/* ID:huang_l1 LANG:C++ PROG:combo */ #include <iostream> #include <cstring> #include <cstdio> using namespace std; #define prt(k) cout<<#k" = "<<k<<endl; const int N = 100005; int head[N], n, m, dep[N], len[N]; /// len[i] 表示 i 到根距离 int val[N]; struct Edge { int to, next, w; }e[N << 1]; int f[N][22]; int mm; int p[N]; void add(int u, int v, int w=1) { e[mm] = (Edge){v, head[u], w}; head[u] = mm++; } int cur; int L[N], R[N]; int to[N]; int cost[N << 1]; void dfs(int u, int fa) { L[u] = ++cur; f[u][0] = fa; p[u] = fa; dep[u] = dep[fa] + 1; for (int i=head[u]; ~i; i=e[i].next) { int v = e[i].to; if (v == fa) continue; to[i / 2] = v; /// to[i] 表示第 i 条边连接的儿子 len[v] = len[u] + e[i].w; dfs(v, u); } R[u] = cur; } int maxh; void gao(int root = 1) { int j; for (j=1;(1<<j)<n;j++) { for (int i=1;i<=n;i++) { f[i][j] = f[ f[i][j-1] ][j-1]; } } maxh = j - 1; } int swim(int x, int k) { for (int i=maxh;i>=0;i--) { if (k >> i & 1) x = f[x][i]; } return x; } int LCA(int x, int y) { if (dep[x] > dep[y]) swap(x, y); y = swim(y, dep[y]-dep[x]); if (x == y) return x; for (int i=maxh;i>=0;i--) { if (f[x][i] != f[y][i]) { x = f[x][i], y = f[y][i]; } } return f[x][0]; } #include <vector> #include <algorithm> int Q, pos; int tree[N << 2]; int low(int x) { return x&-x; } void Add(int p, int x) { for(;p>0;p-=low(p)) tree[p]+=x; } void Add(int l, int r, int x) { Add(r, x); Add(l-1, -x); } int sum(int p) { int ret = 0; for(;p<N;p+=low(p)) ret += tree[p]; return ret; } int getlen(int u) { return sum(L[u]); } int main() { while (cin>>n>>Q>>pos) { mm = 0; memset(head, -1, sizeof head); for (int i=0;i<n-1;i++) { int u,v,w; scanf("%d%d%d", &u, &v, &w); cost[i] = w; add(u,v,w); add(v,u,w); } cur = 0; dfs(1, 0); gao(); memset(tree, 0, sizeof tree); for(int i=1;i<=n;i++) Add(L[i], L[i], len[i]); while (Q--) { int op; scanf("%d", &op); if (op == 0) { int u; scanf("%d", &u); int lca = LCA(pos, u); int ans = getlen(pos) + getlen(u) - 2*getlen(lca); printf("%d\n", ans); pos = u; } else { int id, w; scanf("%d%d", &id, &w); id--; int u = to[id]; Add(L[u], R[u], w - cost[id]); cost[id] = w; } } } }