FZU 2082 过路费

过路费

Time Limit: 1000ms
Memory Limit: 32768KB
This problem will be judged on FZU. Original ID: 2082
64-bit integer IO format: %I64d      Java class name: Main
有n座城市,由n-1条路相连通,使得任意两座城市之间可达。每条路有过路费,要交过路费才能通过。每条路的过路费经常会更新,现问你,当前情况下,从城市a到城市b最少要花多少过路费。
 

Input

有多组样例,每组样例第一行输入两个正整数$n,m(2 \leq n\leq 50000,1\leq m \leq 50000)$,接下来n-1行,每行3个正整数$a b c,(1\leq a,b\leq n , a != b , 1\leq c\leq 1000000000)$.数据保证给的路使得任意两座城市互相可达。接下来输入m行,表示m个操作。

操作有两种:

  1. 0 a b,表示更新第a条路的过路费为b,$1\leq a\leq n-1 $。
  2.  1 a b , 表示询问a到b最少要花多少过路费。
 

Output

对于每个询问,输出一行,表示最少要花的过路费。
 

Sample Input

2 3
1 2 1
1 1 2
0 1 2
1 2 1

Sample Output

1
2

Source

 
解题:树链剖分
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 const int maxn = 50010;
  7 struct arc{
  8     int to,w,next;
  9     arc(int x = 0,int y = 0,int z = -1){
 10         to = x;
 11         w = y;
 12         next = z;
 13     }
 14 }e[maxn<<1];
 15 int head[maxn],fa[maxn],top[maxn],dep[maxn];
 16 int son[maxn],siz[maxn],loc[maxn],clk,tot;
 17 int tree[maxn<<2];
 18 void add(int u,int v,int w){
 19     e[tot] = arc(v,w,head[u]);
 20     head[u] = tot++;
 21 }
 22 void FindHeavyEdge(int u,int father,int depth){
 23     fa[u] = father;
 24     dep[u] = depth;
 25     siz[u] = 1;
 26     son[u] = -1;
 27     for(int i = head[u]; ~i; i = e[i].next){
 28         if(e[i].to == father) continue;
 29         FindHeavyEdge(e[i].to,u,depth + 1);
 30         siz[u] += siz[e[i].to];
 31         if(son[u] == -1 || siz[e[i].to] > siz[son[u]])
 32             son[u] = e[i].to;
 33     }
 34 }
 35 void ConnectHeavyEdge(int u,int ancestor){
 36     top[u] = ancestor;
 37     loc[u] = clk++;
 38     if(son[u] != -1) ConnectHeavyEdge(son[u],ancestor);
 39     for(int i = head[u]; ~i; i = e[i].next){
 40         if(e[i].to == fa[u] || son[u] == e[i].to) continue;
 41         ConnectHeavyEdge(e[i].to,e[i].to);
 42     }
 43 }
 44 void update(int L,int R,int pos,int val,int v){
 45     if(L == R){
 46         tree[v] = val;
 47         return;
 48     }
 49     int mid = (L + R)>>1;
 50     if(pos <= mid) update(L,mid,pos,val,v<<1);
 51     if(pos > mid) update(mid + 1,R,pos,val,v<<1|1);
 52     tree[v] = tree[v<<1] + tree[v<<1|1];
 53 }
 54 int query(int L,int R,int lt,int rt,int v){
 55     if(lt <= L && rt >= R) return tree[v];
 56     int mid = (L + R)>>1,ret = 0;
 57     if(lt <= mid) ret = query(L,mid,lt,rt,v<<1);
 58     if(rt > mid) ret += query(mid + 1,R,lt,rt,v<<1|1);
 59     return ret;
 60 }
 61 int solve(int u,int v,int ret = 0){
 62     while(top[u] != top[v]){
 63         if(dep[top[u]] < dep[top[v]]) swap(u,v);
 64         ret += query(0,clk-1,loc[top[u]],loc[u],1);
 65         u = fa[top[u]];
 66     }
 67     if(u == v) return ret;
 68     if(dep[u] > dep[v]) swap(u,v);
 69     ret += query(0,clk-1,loc[son[u]],loc[v],1);
 70     return ret;
 71 }
 72 int main(){
 73     int n,m,u,v,w,op;
 74     while(~scanf("%d%d",&n,&m)){
 75         memset(head,-1,sizeof head);
 76         clk = tot = 0;
 77         for(int i = 1; i < n; ++i){
 78             scanf("%d%d%d",&u,&v,&w);
 79             add(u,v,w);
 80             add(v,u,w);
 81         }
 82         FindHeavyEdge(1,0,0);
 83         ConnectHeavyEdge(1,1);
 84         memset(tree,0,sizeof tree);
 85         for(int i = 0; i < tot; i += 2){
 86             u = e[i].to;
 87             v = e[i+1].to;
 88             if(dep[u] < dep[v]) swap(u,v);
 89             update(0,clk-1,loc[u],e[i].w,1);
 90         }
 91         while(m--){
 92             scanf("%d%d%d",&op,&u,&v);
 93             if(op) printf("%d\n",solve(u,v));
 94             else{
 95                 int ith = (u-1)*2;
 96                 if(dep[e[ith].to] < dep[e[ith+1].to]) ++ith;
 97                 update(0,clk-1,loc[e[ith].to],v,1);
 98             }
 99         }
100     }
101     return 0;
102 }
View Code

 

posted @ 2015-09-29 10:01  狂徒归来  阅读(178)  评论(0编辑  收藏  举报