Problem 2082 过路费

Accept: 887    Submit: 2881
Time Limit: 1000 mSec    Memory Limit : 32768 KB

 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 <= c <= 1000000000).数据保证给的路使得任意两座城市互相可达。接下来输入m行,表示m个操作,操作有两种:一. 0 a b,表示更新第a条路的过路费为b,1 <= a <= n-1 ; 二. 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
 
思路:
基于边权进行树链剖分
题目说了半天其实就是给你一棵树,修改边权,询问两点之间边的权值和(n个点,n-1条边,点两两互通,摆明了是树结构了),
基于边权的树链剖分和基于点权的处理方面上有些不同。
观察一棵树的结构我们可以看出树上每一个点都可以一一对应和他的父节点相连的边,那么我们就可以用这些点表示树上的边进行
树链剖分。代码算非常裸的树链剖分+线段树区间和,只要注意下一些处理上的小细节就好了。
 
实现代码:
#include<iostream>
#include<cstring>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid ll m = (l + r) >> 1;
const ll M = 1e5+;
ll sum[M<<],son[M],siz[M],head[M],top[M],fa[M],dep[M],tid[M<<],rk[M<<];
ll u[M],v[M],cnt1,cnt,wt[M],n,m;
struct node{
ll to,next,w;
}e[M]; void add(ll u,ll v,ll c){
e[++cnt1].to=v;e[cnt1].next=head[u];e[cnt1].w=c;head[u]=cnt1;
e[++cnt1].to=u;e[cnt1].next=head[v];e[cnt1].w=c;head[v]=cnt1;
}
void dfs1(ll u,ll faz,ll deep){
dep[u] = deep;
siz[u] = ;
fa[u] = faz;
for(ll i = head[u];i ;i=e[i].next){
ll v = e[i].to;
if(v != fa[u]){
wt[v] = e[i].w;
dfs1(v,u,deep+);
siz[u] += siz[v];
if(son[u]==-||siz[v]>siz[son[u]])
son[u] = v;
}
}
} void dfs2(ll u,ll t){
top[u] = t;
tid[u] = cnt;
rk[cnt] = wt[u];
//cout<<1<<endl;
cnt++;
if(son[u] == -) return ;
dfs2(son[u],t);
for(ll i = head[u];i;i=e[i].next){
ll v = e[i].to;
if(v != son[u]&&v != fa[u])
dfs2(v,v);
}
} void pushup(ll rt){
sum[rt] = sum[rt<<] + sum[rt<<|];
} void update(ll p,ll c,ll l,ll r,ll rt){
if(l == r){
sum[rt] = c;
return;
}
mid;
if(p <= m) update(p,c,lson);
else update(p,c,rson);
pushup(rt);
} void build(ll l,ll r,ll rt){
if(l == r){
sum[rt] = rk[l];
return ;
}
mid;
build(lson);
build(rson);
pushup(rt);
} ll query(ll L,ll R,ll l,ll r,ll rt){
if(L <= l&&R >= r){
return sum[rt];
}
mid;
ll ret = ;
if(L <= m) ret += query(L,R,lson);
if(R > m) ret += query(L,R,rson);
return ret;
} ll ask(ll x,ll y){
ll ans = ;
ll fx = top[x],fy = top[y];
while(fx != fy){
if(dep[fx] < dep[fy]) swap(fx,fy),swap(x,y);
if(fx == ) ans += query(tid[fx]+,tid[x],,n,);
else ans += query(tid[fx],tid[x],,n,);
x = fa[fx]; fx = top[x];
}
//当x,y top相同时,因为当前这个点代表的是它与父节点之前的边的权值
//top相同时有两种情况:1。两点重合,2.两点在同一重链上
if(x==y) return ans; //两点重合时直接返回当前的值就好了。
if(dep[x] > dep[y]) swap(x,y);
ans += query(tid[x]+,tid[y],,n,); //当两点在同一重链上时,dep较小的边需要+1。
return ans;
} void init()
{
memset(son,-,sizeof(son));
for(ll i = ; i <= n;i ++){
e[i].to = ;e[i].w = ;e[i].next = ;head[i] = ;
}
}
int main()
{
ios::sync_with_stdio();
cin.tie(); cout.tie();
ll c,x,a,b;
while(cin>>n>>m){
init();
cnt1 = ;cnt = ;
for(ll i = ;i < n;i ++){
cin>>u[i]>>v[i]>>c;
add(u[i],v[i],c);
}
dfs1(,,);
dfs2(,);
//cout<<1<<endl;
build(,n,);
while(m--){
cin>>x>>a>>b;
if(x==){
if(dep[u[a]] < dep[v[a]]) swap(u[a],v[a]);
update(tid[u[a]],b,,n,);
}
else{
cout<<ask(a,b)<<endl;
}
}
}
return ;
}

fzu 2082 过路费 (树链剖分+线段树 边权)的更多相关文章

  1. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  2. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  3. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  4. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  5. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  6. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  7. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  8. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

  9. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

随机推荐

  1. HDU 2647 Reward(拓扑排序,vector实现邻接表)

    Reward Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Subm ...

  2. day 43

    今日内容 1.视图 2.事务 3.SQL注入问题 4.存储过程 首先回顾一下昨天所学 子查询: in (select a where 字段名 in select b) exists(判断后面语句执行结 ...

  3. sql语句截取字符串

    Postgresql 当中有四种方式获取当前时间.  一:now()      通过now()获取的时间是最完整的时间,包括时区,秒也保留到了6位小数.      select now();     ...

  4. [Lydsy1805月赛]对称数 BZOJ5361

    分析: 这个题,还是蛮有趣的.考虑,如果l,r区间内的所有数出现奇数次,那么[l-1,r]的抑或和等于所得抑或和. 之后怎么维护呢,主席树维护区间抑或和,记得将每个点附上一个ull级别的随机数,之后抑 ...

  5. c# update check

    public class UpdateChecker { public static event EventHandler completeCheck; private static bool isC ...

  6. sinopia 搭建记录

    最近公司有个问题,一些公共部分每次都要手动发送,放到 git 上涉及到父子 git 问题,现在就想在内部搭建一个 npm,涉及到公共模块了就直接 npm update 更新一下.找到了 sinopia ...

  7. POJ 1459&&3436

    两道比较基础的网络流题目,重点就是建图. 1458:题意就是给你一些东西它们的数据,其中一些是发电站,还有一些是用户的家里,其中还有一些是中转站.让你求最大的输送电量. 就是一道很基础的最大流题目,建 ...

  8. 隐马尔科夫模型研究 stock 以及 lotto

    说明 本文参考了这里 由于数据是连续的,因此使用了高斯隐马尔科夫模型:gaussianHMM 一.stock代码 import tushare as ts import pandas as pd im ...

  9. OpenCV学习C++接口 Mat像素遍历详解

    OpenCV学习C++接口 Mat像素遍历详解

  10. mybatis源码-解析配置文件(三)之配置文件Configuration解析

    目录 1. 简介 1.1 系列内容 1.2 适合对象 1.3 本文内容 2. 配置文件 2.1 mysql.properties 2.2 mybatis-config.xml 3. Configura ...