Loading

POJ 2763:Housewife Wind(树链剖分)

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\n", 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 */

 

posted @ 2016-10-30 19:57  Shadowdsp  阅读(146)  评论(0编辑  收藏  举报