http://poj.org/problem?id=2763
题意:给出 n 个点, n-1 条带权边, 询问是询问 s 到 v 的权值, 修改是修改存储时候的第 i 条边的权值。
思路:树链剖分之修改边权。边权的修改, 与点权修改不同的地方在于, 线段树中存的点是边,其中每条边边是以 儿子 的时间戳来记录的。例如: u -> v , dep[u] < dep[v], 说明 u 是 v 的父亲,所以这条边在线段树中的编号就是以 tid[v].
1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <string> 6 #include <cmath> 7 #include <queue> 8 #include <vector> 9 using namespace std; 10 #define N 100005 11 #define INF 0x3f3f3f3f 12 #define lson rt<<1, l, m 13 #define rson rt<<1|1, m+1, r 14 struct node 15 { 16 int v, w, next; 17 }edge[N*2]; 18 int head[N], tot; 19 int time, tid[N], fa[N], rak[N], son[N], dep[N], size[N], top[N]; 20 int tree[N<<2]; 21 int e[N][3]; 22 23 /* 24 树链剖分: 边权的修改, 与点权修改不同的地方在于, 线段树中存的点是边, 25 其中每条边边是以 儿子 的时间戳来记录的 26 例如: u -> v , dep[u] < dep[v], 说明 u 是 v 的父亲, 27 所以这条边在线段树中的编号就是以 tid[v] 的形式来存储. 28 */ 29 30 void init() 31 { 32 memset(head, -1, sizeof(head)); 33 memset(son, -1, sizeof(son)); 34 memset(fa, 0, sizeof(fa)); 35 time = tot = 0; 36 } 37 38 void add(int u, int v, int w) 39 { 40 edge[tot].next = head[u]; edge[tot].v = v; edge[tot].w = w; head[u] = tot++; 41 } 42 43 void dfs1(int u, int f, int d) 44 { 45 size[u] = 1; 46 dep[u] = d; 47 fa[u] = f; 48 for(int i = head[u]; ~i; i = edge[i].next) { 49 int v = edge[i].v; 50 if(v == f) continue; 51 dfs1(v, u, d + 1); 52 size[u] += size[v]; 53 if(son[u] == -1 || size[son[u]] < size[v]) 54 son[u] = v; 55 } 56 } 57 58 void dfs2(int u, int f) 59 { 60 tid[u] = ++time; 61 top[u] = f; 62 rak[time] = u; 63 if(son[u] == -1) return ; 64 dfs2(son[u], f); 65 for(int i = head[u]; ~i; i = edge[i].next) { 66 int v = edge[i].v; 67 if(v != son[u] && v != fa[u]) { 68 dfs2(v, v); 69 } 70 } 71 } 72 73 void build(int rt, int l, int r) 74 { 75 tree[rt] = 0; 76 if(l == r) return ; 77 int m = (l + r) >> 1; 78 build(lson); build(rson); 79 } 80 81 void pushup(int rt) 82 { 83 tree[rt] = tree[rt<<1] + tree[rt<<1|1]; 84 } 85 86 void update(int rt, int l, int r, int id, int w) 87 { 88 if(l == id && r == id) { 89 tree[rt] = w; 90 return ; 91 } 92 if(l == r) return ; 93 int m = (l + r) >> 1; 94 if(id <= m) update(lson, id, w); 95 else update(rson, id, w); 96 pushup(rt); 97 } 98 99 long long query(int rt, int l, int r, int L, int R) 100 { 101 long long ans = 0; 102 if(L <= l && r <= R) { 103 ans += tree[rt]; 104 return ans; 105 } 106 int m = (l + r) >> 1; 107 if(L <= m) ans += query(lson, L, R); 108 if(m < R) ans += query(rson, L, R); 109 return ans; 110 } 111 112 long long change(int u, int v) 113 { 114 long long ans = 0; 115 int tp1 = top[u], tp2 = top[v]; 116 while(top[u] != top[v]) { 117 if(dep[top[u]] < dep[top[v]]) swap(u, v); 118 ans += query(1, 1, time, tid[top[u]], tid[u]); 119 u = fa[top[u]]; 120 } 121 if(dep[u] > dep[v]) swap(u, v); 122 if(u == v) return ans; // 如果是同一个点, 就不能继续询问了 123 ans += query(1, 1, time, tid[son[u]], tid[v]); 124 return ans; 125 } 126 127 int main() 128 { 129 int n, q, s; 130 scanf("%d%d%d", &n, &q, &s); 131 init(); 132 for(int i = 1; i < n; i++) { 133 int u, v, w; 134 scanf("%d%d%d", &u, &v, &w); 135 e[i][0] = u, e[i][1] = v, e[i][2] = w; 136 add(u, v, w); add(v, u, w); 137 } 138 dfs1(s, s, 1); 139 dfs2(s, s); 140 build(1, 1, time); 141 for(int i = 1; i < n; i++) { 142 if(dep[e[i][0]] > dep[e[i][1]]) swap(e[i][0], e[i][1]); 143 update(1, 1, time, tid[e[i][1]], e[i][2]); 144 } 145 for(int i = 0; i < q; i++) { 146 int o, a, b; 147 scanf("%d", &o); 148 if(o == 1) { 149 scanf("%d%d", &a, &b); 150 update(1, 1, time, tid[e[a][1]], b); 151 } else { 152 scanf("%d", &a); 153 long long ans = change(s, a); 154 s = a; 155 printf("%lld ", ans); 156 } 157 } 158 return 0; 159 } 160 161 /* 162 4 4 1 163 1 2 1 164 2 3 2 165 1 4 1 166 0 2 167 1 2 3 168 0 3 169 0 4 170 */