B. Diverging Directions

题意

给出一个n个点2n-2条边的有向图。n-1条指向远离根方向的边形成一棵树,还有n-1条从非根节点指向根节点的边。

q次操作,1修改第x条边权值为y,2询问,求u到v的最短距离。

题解

在前n-1条边上dfs得到dfs序。

用线段树维护从根到区间里的点的最短距离,和从根到区间里的点再回去的最短距离。

修改第一条边的边权时,就修改了根到这条边指向的点为根的子树里每个点的距离。x为根的子树的点dfs序为L[x]~R[x]。

修改第二种边的边权时,只影响根到这条边出发点再回去的最短距离。

查询时,如果u是v的祖先,最短距离就是根到v的距离减去根到u的距离;不是祖先时,那就是从u为根的子树里的点回到根的最短距离加上根到v的距离。

代码

#include <bits/stdc++.h>
#define N 1<<18
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a)) using namespace std; struct SegTree{
int n;
ll tree[N<<2],lazy[N<<2];
void init(int _n){
n=_n;
mem(tree,0);
mem(lazy,0);
}
void pushdown(int node){
lazy[node<<1]+=lazy[node];
tree[node<<1]+=lazy[node];
lazy[node<<1|1]+=lazy[node];
tree[node<<1|1]+=lazy[node];
lazy[node]=0;
}
void update(int node,int l,int r,int L,int R,ll value){
if(L>R || l>R || r<L) return;
if(L<=l && r<=R){
tree[node]+=value;
lazy[node]+=value;
return;
}
pushdown(node);
update(node<<1,l,l+r>>1,L,R,value);
update(node<<1|1,(l+r>>1)+1,r,L,R,value); tree[node]=min(tree[node<<1],tree[node<<1|1]);
}
ll query(int node,int l,int r,int L,int R){
if(L>R || l>R || r<L) return numeric_limits < ll > ::max();
if(L<=l && r<=R){
return tree[node];
}
pushdown(node);
return min(query(node<<1,l,l+r>>1,L,R),
query(node<<1|1,(l+r>>1)+1,r,L,R));
}
void update(int L,int R,ll value){
update(1,1,n,L,R,value);
}
ll query(int L,int R){
return query(1,1,n,L,R);
}
}from_root,from_root_and_back; struct Edge{
int to,next,w;
}e[N];
int head[N],cnt;
void add(int u,int v,int w){
e[++cnt]=(Edge){v,head[u],w};
head[u]=cnt;
}
int from[N<<1]; int L[N],R[N],idx;
ll dis[N];
void dfs(int x,int fa){
L[x]=R[x]=++idx;
for(int i=head[x];i;i=e[i].next){
int v=e[i].to;
if(v!=fa){
dis[v]=dis[x]+e[i].w;
dfs(v,x);
R[x]=R[v];
}
}
} ll dep(int x){
return from_root.query(L[x],L[x]);
} ll back[N];
int main(){
int n,q;
scanf("%d%d", &n, &q);
int u,v,w;
for(int i=1;i<n;++i){
scanf("%d%d%d", &u, &v, &w);
add(u,v,w);
from[i]=u;
}
for(int i=1;i<n;++i){
scanf("%d%d%d", &u, &v, &w);
back[u]=w;
from[i+n-1]=u;
} from_root.init(n);
from_root_and_back.init(n); dfs(1,0); for(int i=1;i<=n;++i){
from_root.update(L[i],L[i],dis[i]);
from_root_and_back.update(L[i],L[i],dis[i]+back[i]);
} while(q--) {
int o,x,y;
scanf("%d%d%d", &o, &x, &y);
if(o&1) {
if(x<n) {
int v=e[x].to,u=from[x],d=y-dep(v)+dep(u);
from_root.update(L[v],R[v],d);
from_root_and_back.update(L[v],R[v],d);
}
else {
int u=from[x],d=y-back[u];back[u]=y;
from_root_and_back.update(L[u],L[u],d);
}
}
else {
if(L[x]<=L[y]&&R[y]<=R[x])
printf("%lld\n", dep(y)-dep(x));
else
printf("%lld\n",from_root_and_back.query(L[x],R[x])-dep(x)+dep(y));
}
}
return 0;
}

「CF838B」 Diverging Directions的更多相关文章

  1. 「干货」面试官问我如何快速搜索10万个矩形?——我说RBush

    「干货」面试官问我如何快速搜索10万个矩形?--我说RBUSH 前言 亲爱的coder们,我又来了,一个喜欢图形的程序员‍,前几篇文章一直都在教大家怎么画地图.画折线图.画烟花,难道图形就是这样嘛,当 ...

  2. 「译」JUnit 5 系列:条件测试

    原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...

  3. 「译」JUnit 5 系列:扩展模型(Extension Model)

    原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...

  4. JavaScript OOP 之「创建对象」

    工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...

  5. 「C++」理解智能指针

    维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...

  6. 「JavaScript」四种跨域方式详解

    超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...

  7. 「2014-5-31」Z-Stack - Modification of Zigbee Device Object for better network access management

    写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉: ...

  8. 「2014-3-18」multi-pattern string match using aho-corasick

    我是擅(倾)长(向)把一篇文章写成杂文的.毕竟,写博客记录生活点滴,比不得发 paper,要求字斟句酌八股结构到位:风格偏杂文一点,也是没人拒稿的.这么说来,arxiv 就好比是 paper 世界的博 ...

  9. 「2014-3-17」C pointer again …

    记录一个比较基础的东东-- C 语言的指针,一直让人又爱又恨,爱它的人觉得它既灵活又强大,恨它的人觉得它太过于灵活太过于强大以至于容易将人绕晕.最早接触 C 语言,还是在刚进入大学的时候,算起来有好些 ...

随机推荐

  1. C. Painting the Fence

    链接 [https://codeforces.com/contest/1132/problem/C] 题意 就是有个n长的栅栏,然后每个油漆工可以染的区域不同 给你q让你选出q-2个人使得被染色的栅栏 ...

  2. c++ 入门之对象指针

    我们想 像使用基本数据类型一样使用类,自然,类自然也有指针,我们通过下面的代码来领教一下对象指针存在的意义: # include "iostream" # include &quo ...

  3. 斐波那契数列yield表示

    def fib(num): n=0 a,b=0,1 while n<num: print(b) yield a,b=b,a+b n=n+1a=fib(30)next(a)next(a)  

  4. ntpd、ntpdate、hwclock的区别

    hwclock --systohc 使用ntpdate更新系统时间 - 潜龙勿用 - CSDN博客https://blog.csdn.net/suer0101/article/details/7868 ...

  5. js 翻牌活动效果

    直接上代码 html: <div class="index_main"> <ul class="index_card"> <li ...

  6. Day1 基础知识

    数据类型,字符编码 二进制: 定义:二进制数据是用0和1两个数码来表示的数.它的基数为2,进位规则是“逢二进一”,借位规则是“借一当二”.当前的计算机系统使用的基本上是二进制系统,数据在计算机中主要是 ...

  7. 6s ios9.0平台 微信小程序的fixed定位兼容性问题

    如果不设置top和left的话  就会出现不显示问题

  8. servlet中将值以json格式传入

    详细连接https://blog.csdn.net/e_wsq/article/details/71038270$('#but_json_json').click(function(){ }; $.a ...

  9. 本地git连接远程github

    git要连接GitHub仓库,是通过SSH加密连接的,所以必须要创建SSH key ssh-key -t rsa -C "youremail@example.com" 这里邮箱必须 ...

  10. 老男孩python学习自修第七天【包与模块】

    1.如何导入 from package import module module.function() 常用魔术方法 __init__.py 如果某个文件夹下面有该文件,则该文件夹是一个包,否则只是一 ...