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. sql 表值函数与标量值函数

    写sql存储过程经常需要调用一些函数来使处理过程更加合理,也可以使函数复用性更强,不过在写sql函数的时候可能会发现,有些函数是在表值函数下写的有些是在标量值下写的,区别是表值函数只能返回一个表,标量 ...

  2. scrapy框架爬取妹子图片

    首先,建立一个项目#可在github账户下载完整代码:https://github.com/connordb/scrapy-jiandan2 scrapy startproject jiandan2 ...

  3. ElasticSearch聚合

    前言 说完了ES的索引与检索,接着再介绍一个ES高级功能API – 聚合(Aggregations),聚合功能为ES注入了统计分析的血统,使用户在面对大数据提取统计指标时变得游刃有余.同样的工作,你在 ...

  4. Java面试题详解三:比较器

    一,Comparable和Comparator1.Comparable可以认为是一个内比较器,实现了Comparable接口的类有一个特点,就是这些类是可以和自己比较.Comparable接口中只有一 ...

  5. Use the Microsoft Symbol for VS and Windbg

    快捷方式mklink的远程符号由于所有者权限问题,链接到本地可能造成不能使用, 或每次都需要重新下载, 1.环境变量中没有设置_NT_SYMBOL_PATH的值 2.windbg快捷方式中也没有设置- ...

  6. Pyspider上手

    pyspider安装: pip3 install Pyspider 启动服务操作 1.打开cmd:输入        pyspider  --help 回车,可以查看帮助信息,pyspider all ...

  7. css实现三栏自适应布局(两边固定,中间自适应)以及优缺点

    方法一:绝对定位(absolute + margin) 原理:给左右两边的元素设置absolute,这样左右两边的元素脱离标准文档流的控制,中间的元素自然会上来,然后给中间的元素设置margin留出左 ...

  8. Azure系列2.1.5 —— BlobOutputStream

    (小弟自学Azure,文中有不正确之处,请路过各位大神指正.) 网上azure的资料较少,尤其是API,全是英文的,中文资料更是少之又少.这次由于公司项目需要使用Azure,所以对Azure的一些学习 ...

  9. Azure系列2.1.2 —— BlobContainerProperties

    (小弟自学Azure,文中有不正确之处,请路过各位大神指正.) 网上azure的资料较少,尤其是API,全是英文的,中文资料更是少之又少.这次由于公司项目需要使用Azure,所以对Azure的一些学习 ...

  10. MyBatis映射文件4(参数获取#{}和${}/select标签详解[返回类型为list])

    参数获取 之前我们都是采用#{}的方式进行参数传递,其实MyBatis还有另外的参数传递方式${} 使用方法相同,但是还是有很大区别的 这里做一个测试: <select id="get ...