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

FOJ有奖月赛-2012年4月(校赛热身赛)

解题:树链剖分

  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 }

时间: 2024-10-22 10:55:33

FZU 2082 过路费的相关文章

FZU 2082 过路费(树链抛分)

FZU 2082 过路费 题目链接 树链抛分修改边的模板题 代码: #include <cstdio> #include <cstring> #include <vector> using namespace std; typedef long long ll; const int N = 50005; int dep[N], id[N], sz[N], top[N], son[N], fa[N], idx; int n, m; ll bit[N]; struct Ed

FZU 2082 过路费(树链剖分)

FZU 2082 过路费 题目链接 树链抛分改动边的模板题 代码: #include <cstdio> #include <cstring> #include <vector> using namespace std; typedef long long ll; const int N = 50005; int dep[N], id[N], sz[N], top[N], son[N], fa[N], idx; int n, m; ll bit[N]; struct Ed

FZU 2082 过路费 (树链剖分)边权

Problem 2082 过路费 Accept: 322    Submit: 1101 Time Limit: 1000 mSec    Memory Limit : 32768 KB Problem Description 有n座城市,由n-1条路相连通,使得任意两座城市之间可达.每条路有过路费,要交过路费才能通过.每条路的过路费经常会更新,现问你,当前情况下,从城市a到城市b最少要花多少过路费. Input 有多组样例,每组样例第一行输入两个正整数n,m(2 <= n<=50000,1&

FZU 2082 过路费 (树链剖分)

树链剖分裸题...不多说.. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include <stdio.h> using namespace

FZU Problem 2082 过路费 树链剖分

Problem 2082 过路费  Problem Description 有n座城市,由n-1条路相连通,使得任意两座城市之间可达.每条路有过路费,要交过路费才能通过.每条路的过路费经常会更新,现问你,当前情况下,从城市a到城市b最少要花多少过路费.  Input 有多组样例,每组样例第一行输入两个正整数n,m(2 <= n<=50000,1<=m <= 50000),接下来n-1行,每行3个正整数a b c,(1 <= a,b <= n , a != b , 1 &

FZU 2082(过路费)

题目链接:传送门 题目大意:中文题,略 题目思路:树链剖分(注意要把边上的权值转移到深度较大的点上来维护) 最后当top[x]==top[y]注意id[x]+1因为是维护的点而题目是边 如果不+可能会出现重复加的情况. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cmath> 5 #include <algorithm> 6 #include

Problem 2082 过路费树链剖分

裸题直接搞. #include<iostream> #include<cstdio> #include<cstring> #include<map> #include<vector> #include<stdlib.h> using namespace std; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 typedef long long LL;

FZU 2082 树链剖分

点击打开链接 题意:中文 思路:最基础的树链剖分,区间求和以及单点更新,结果要用long long 就没什么了 #include <vector> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; ty

树链剖分 FZU 2082

#include<cstring> #include<cstdio> #include<algorithm> using namespace std; const int maxn = 50005; int val[maxn]; struct node { int l,r; long long sum; } xds[maxn<<2]; void build(int ID,int l,int r) { xds[ID].l=l; xds[ID].r=r; if(