FZU2082

树链剖分后要处理的是边的权值,而不是点的权值,但是只要边权下放到点,就可以了

如图

但是问题是,求图4->5路径的权值之和, 那么就会把点3给算进去

那么就要减去,

或者干脆不加进去

有两种方法

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include <algorithm>
  5 #include <iostream>
  6 #include <queue>
  7 #include <stack>
  8 #include <vector>
  9 #include <map>
 10 #include <set>
 11 #include <string>
 12 #include <math.h>
 13 using namespace std;
 14 #pragma warning(disable:4996)
 15 #pragma comment(linker, "/STACK:1024000000,1024000000")
 16 typedef long long LL;                   
 17 const int INF = 1<<30;
 18 /*
 19 12 1
 20 1 2 1
 21 2 3 1
 22 3 4 1
 23 4 5 1
 24 5 11 1
 25 11 12 1
 26 1 6 1
 27 6 7 1
 28 7 8 1
 29 6 9 1
 30 6 10 1
 31 1 9 10
 32 */
 33 const int N = 50000 + 10;
 34 vector<int> g[N];
 35 int size[N], son[N], fa[N], depth[N], top[N], w[N], num, ra[N];
 36 LL tree[N*4];
 37 int edge[N][3];
 38 int h[N];
 39 void dfs(int u)
 40 {
 41     size[u] = 1;
 42     son[u] = 0;
 43     for (int i = 0; i < g[u].size(); ++i)
 44     {
 45         int v = g[u][i];
 46         if (v != fa[u])
 47         {
 48             fa[v] = u;
 49             depth[v] = depth[u] + 1;
 50             dfs(v);
 51             size[u] += size[v];
 52             if (size[v] > size[son[u]])
 53                 son[u] = v;
 54         }
 55     }
 56 }
 57 
 58 void dfs2(int u, int tp)
 59 {
 60     w[u] = ++num;
 61     ra[num] = u;
 62     top[u] = tp;
 63     if (son[u] != 0)
 64         dfs2(son[u], top[u]);
 65     for (int i = 0; i < g[u].size(); ++i)
 66     {
 67         int v = g[u][i];
 68         if (v != fa[u] && v != son[u])
 69             dfs2(v, v);
 70     }
 71     
 72 }
 73 void pushUp(int rt)
 74 {
 75     tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];
 76 }
 77 void update(int l, int r, int rt, int pos, int val)
 78 {
 79     if (l == r)
 80     {
 81         tree[rt] = val;
 82         return;
 83     }
 84     int mid = (l + r) >> 1;
 85     if (pos <= mid)
 86         update(l, mid, rt << 1, pos, val);
 87     else
 88         update(mid + 1, r, rt << 1 | 1, pos, val);
 89     pushUp(rt);
 90 }
 91 
 92 LL ans;
 93 void query(int l, int r, int rt, int L, int R)
 94 {
 95     if (L <= l&&R >= r)
 96     {
 97         ans += tree[rt];
 98         return;
 99     }
100     int mid = (l + r) >> 1;
101     if (L <= mid)
102         query(l, mid, rt << 1, L, R);
103     if (R > mid)
104         query(mid + 1, r, rt << 1 | 1, L, R);
105 }
106 int main()
107 {
108     int n, m, a, b, c;
109     while (scanf("%d%d", &n, &m) != EOF)
110     {
111         memset(tree, 0, sizeof(tree));
112         for (int i = 1; i <= n; ++i)
113             g[i].clear();
114         num = 0;
115         for (int i = 1; i < n; ++i)
116         {
117             scanf("%d%d%d", &edge[i][0], &edge[i][1], &edge[i][2]);
118             g[edge[i][0]].push_back(edge[i][1]);
119             g[edge[i][1]].push_back(edge[i][0]);
120         }
121         fa[1] = depth[1] = 0;
122         dfs(1);
123         dfs2(1, 1);
124         for (int i = 1; i < n; ++i)
125         {
126             if (depth[edge[i][0]] > depth[edge[i][1]])
127                 swap(edge[i][0], edge[i][1]);
128             h[edge[i][1]] = edge[i][2];
129             update(1, n, 1, w[edge[i][1]], edge[i][2]);
130         }
131         while (m--)
132         {
133             scanf("%d%d%d", &a, &b, &c);
134             if (a == 0)
135             {
136                 if (depth[edge[b][0]] > depth[edge[b][1]])
137                     swap(edge[b][0], edge[b][1]);
138                 update(1, n, 1, w[edge[b][1]], c);
139                 h[edge[b][1]] = c;
140             }
141             else
142             {
143                 ans = 0;
144                 while (top[b] != top[c])
145                 {
146                     if (depth[top[b]] < depth[top[c]])
147                         swap(b, c);
148                     query(1, n, 1, w[top[b]], w[b]);
149                     b = fa[top[b]];
150                 }
151                 //b和c一定是在一条链上
152                 if (depth[b]>depth[c])
153                     swap(b, c);
154                 
155                 
156                 //如果b有父亲,那么就有边下放到它,多加了这个点,要减去
157                 query(1, n, 1, w[b], w[c]);
158                 if (fa[b] != 0)
159                     ans -= h[b];
160                 /*
161                 如果b,c是在一条重链上, 那么询问w[son[b]] 到w[c]
162                 那么就没有加到点b
163                 否则,b,c就是指向同一点,那么w[son[b]] > w[c] , 询问是不会增加任何值的
164                 query(1, n, 1, w[son[b]], w[c]);
165                 */
166                 printf("%lld\n", ans);
167             }
168         }
169     }
170     return 0;
171 }
View Code

 

posted @ 2015-07-06 00:39  justPassBy  阅读(181)  评论(0编辑  收藏  举报