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的距离。

代码

  1. #include <bits/stdc++.h>
  2. #define N 1<<18
  3. #define ll long long
  4. #define mem(a,b) memset(a,b,sizeof(a))
  5. using namespace std;
  6. struct SegTree{
  7. int n;
  8. ll tree[N<<2],lazy[N<<2];
  9. void init(int _n){
  10. n=_n;
  11. mem(tree,0);
  12. mem(lazy,0);
  13. }
  14. void pushdown(int node){
  15. lazy[node<<1]+=lazy[node];
  16. tree[node<<1]+=lazy[node];
  17. lazy[node<<1|1]+=lazy[node];
  18. tree[node<<1|1]+=lazy[node];
  19. lazy[node]=0;
  20. }
  21. void update(int node,int l,int r,int L,int R,ll value){
  22. if(L>R || l>R || r<L) return;
  23. if(L<=l && r<=R){
  24. tree[node]+=value;
  25. lazy[node]+=value;
  26. return;
  27. }
  28. pushdown(node);
  29. update(node<<1,l,l+r>>1,L,R,value);
  30. update(node<<1|1,(l+r>>1)+1,r,L,R,value);
  31. tree[node]=min(tree[node<<1],tree[node<<1|1]);
  32. }
  33. ll query(int node,int l,int r,int L,int R){
  34. if(L>R || l>R || r<L) return numeric_limits < ll > ::max();
  35. if(L<=l && r<=R){
  36. return tree[node];
  37. }
  38. pushdown(node);
  39. return min(query(node<<1,l,l+r>>1,L,R),
  40. query(node<<1|1,(l+r>>1)+1,r,L,R));
  41. }
  42. void update(int L,int R,ll value){
  43. update(1,1,n,L,R,value);
  44. }
  45. ll query(int L,int R){
  46. return query(1,1,n,L,R);
  47. }
  48. }from_root,from_root_and_back;
  49. struct Edge{
  50. int to,next,w;
  51. }e[N];
  52. int head[N],cnt;
  53. void add(int u,int v,int w){
  54. e[++cnt]=(Edge){v,head[u],w};
  55. head[u]=cnt;
  56. }
  57. int from[N<<1];
  58. int L[N],R[N],idx;
  59. ll dis[N];
  60. void dfs(int x,int fa){
  61. L[x]=R[x]=++idx;
  62. for(int i=head[x];i;i=e[i].next){
  63. int v=e[i].to;
  64. if(v!=fa){
  65. dis[v]=dis[x]+e[i].w;
  66. dfs(v,x);
  67. R[x]=R[v];
  68. }
  69. }
  70. }
  71. ll dep(int x){
  72. return from_root.query(L[x],L[x]);
  73. }
  74. ll back[N];
  75. int main(){
  76. int n,q;
  77. scanf("%d%d", &n, &q);
  78. int u,v,w;
  79. for(int i=1;i<n;++i){
  80. scanf("%d%d%d", &u, &v, &w);
  81. add(u,v,w);
  82. from[i]=u;
  83. }
  84. for(int i=1;i<n;++i){
  85. scanf("%d%d%d", &u, &v, &w);
  86. back[u]=w;
  87. from[i+n-1]=u;
  88. }
  89. from_root.init(n);
  90. from_root_and_back.init(n);
  91. dfs(1,0);
  92. for(int i=1;i<=n;++i){
  93. from_root.update(L[i],L[i],dis[i]);
  94. from_root_and_back.update(L[i],L[i],dis[i]+back[i]);
  95. }
  96. while(q--) {
  97. int o,x,y;
  98. scanf("%d%d%d", &o, &x, &y);
  99. if(o&1) {
  100. if(x<n) {
  101. int v=e[x].to,u=from[x],d=y-dep(v)+dep(u);
  102. from_root.update(L[v],R[v],d);
  103. from_root_and_back.update(L[v],R[v],d);
  104. }
  105. else {
  106. int u=from[x],d=y-back[u];back[u]=y;
  107. from_root_and_back.update(L[u],L[u],d);
  108. }
  109. }
  110. else {
  111. if(L[x]<=L[y]&&R[y]<=R[x])
  112. printf("%lld\n", dep(y)-dep(x));
  113. else
  114. printf("%lld\n",from_root_and_back.query(L[x],R[x])-dep(x)+dep(y));
  115. }
  116. }
  117. return 0;
  118. }

「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. 01-HTML介绍

    1.WEB标准 web准备介绍: w3c:万维网联盟组织,用来制定web标准的机构(组织) web标准:制作网页遵循的规范 web准备规范的分类:结构标准.表现标准.行为标准. 结构:html.表示: ...

  2. 替换iframe的内容

    一般就是点个按钮然后在不跳转页面的情况下显示另外一个页面的内容,显示的速度比较快,ifream还算是常用的吧 用的时候实现方式有以下几种, 1.替换src路径(觉得麻烦,没接触过,就不这样干了) 2. ...

  3. Vue向后端请求课程展示

    1.Vue结构 App.vue <template> <div id="app"> <router-link to="/index" ...

  4. 福州大学软件工程1816 | W班 第3次作业成绩排名

    写在前面 汇总成绩排名链接 1.作业链接 第三次作业--原型设计(结对第一次) 2.评分准则 本次作业总分 25分,由以下部分组成: (1)在随笔开头请加上该博客链接,以方便阅读时查看作业需求,并备注 ...

  5. hadoop实例-网站用户行为分析

    一.数据集 网站用户购物行为数据集2030万条,包括raw_user.csv(2000万条)和small_user.csv(30万条,适合新手) 字段说明: user_id 用户编号,item_id ...

  6. VMware虚拟机与Windows文件共享

    开发中,我们经常的需求是这样的:我想再Windows中进行快捷开发,但是想在linux中运行,那么需要将文件方便在linux中管理,基本可以分成两种方式: 1. 使用网络工具:vmware_tool工 ...

  7. JMeter压测分布式部署

    监控JMeter压力机的性能

  8. js手机短信验证

    贴代码之前,我们先讲一下这里我们用到的技术主要有1个.setInterval(),这个方法可以实现倒计时的效果. css: .weui_btn_disabled.weui_btn_default { ...

  9. Oracle 内存参数调优设置

    Oracle 数据库系统中起到调节作用的参数叫初始化参数,数据库管理员根据实际情况需要适当调整这些 初始化参数以优化Oracle系统. 1 主要系统参数调优介绍 2 系统内存参数的分配 2.1 Ora ...

  10. [官网]CREATE EXTENSION PostGreSQL 创建函数的方法

    CREATE EXTENSION https://www.postgresql.org/docs/current/sql-createextension.html CREATE EXTENSION — ...