传送门:Problem 2763

https://www.cnblogs.com/violet-acmer/p/9686774.html

题意:

  一对夫妇居住在xx村庄,小屋之间有双向可达的道路,不会出现环,即所构成的图是个树,从ai小屋到bi小屋需要花费wi时间,一开始,女主角在s小屋,有两个询问,

  ①0 u : 她又个孩子在u屋,需要妈妈接她回家,输出从s到u所需的最短时间。

  ②1 x val : 由于种种原因,第x条道路的行走时间由之前的w[x]变为了val。

题解:

  (1)RMQ+BIT

    因为树中连接两点的路径是唯一的,如果我们对顶点进行合理排列的话,能否像链状时那样,进行类似的处理呢?

    考虑利用RMQ计算LCA时所用的,按DFS访问的顺序排列顶点序列。

    这样,u和v之间的路径,就是在序列中u 和 v 之间的所有边减去往返重复的部分得到的结果。

    于是,只要令边的权重沿叶子方向为正,沿根方向为负,那么往返重复的部分就自然抵消了,于是有

        (u,v之间的花费的时间)=(从LCA(u,v)到u的花费的时间和)+(从LCA(u,v)到v的花费的时间和);

    同链状情况一样,利用BIT的话,计算权重和更新边权都可以在O(logn)时间内办到,而LCA也能够在O(longn)时间内求得。

  (2)树链剖分

AC代码:

 #include<iostream>
 #include<cstdio>
 #include<cmath>
 #include<cstring>
 #include<vector>
 using namespace std;
 #define pb push_back
 #define mem(a,b) (memset(a,b,sizeof a))
 #define lowbit(x) (x&(-x))
 ;

 int n,q,s;
 int w[maxn];//存储第 i 条边的权值
 struct Node
 {
     int to;
     int w;
     int id;
     Node(int to,int w,int id):to(to),w(w),id(id){}
 };
 vector<Node >G[maxn];
 void addEdge(int u,int v,int cost,int id)
 {
     G[u].pb(Node(v,cost,id));
     G[v].pb(Node(u,cost,id));
 }
 *maxn];//欧拉序列
 *maxn];//深度序列
 int id[maxn];//id[i] : 记录节点 i 在欧拉序列中第一次出现的位置
 *maxn];//边的下标,i*2 : 叶子方向 i*2+1 : 根方向
 int total;//记录欧拉序列的下标总个数,其实最终的 total = 2*n
 //================BIT==================
 *maxn];//树状数组
 void Add(int x,int val)
 {
     *maxn)
     {
         bit[x] += val;
         x += lowbit(x);
     }
 }
 int Sum(int x)
 {
     ;
     )
     {
         sum += bit[x];
         x -= lowbit(x);
     }
     return sum;
 }
 //=====================================
 //==================RMQ================
 struct RMQ
 {
     ][*maxn];
     void Init(){
         ;i < *maxn;++i)
             dp[][i]=i;
     }
     void ST()
     {
         );
         ;i <= k;++i)
             ;j <= (total-(<<i));++j)
                 ][j]] > depth[dp[i-][j+(<<(i-))]])//dp[i][j] : 记录的是下标
                     dp[i][j]=dp[i-][j+(<<(i-))];
                 else
                     dp[i][j]=dp[i-][j];
     }
     int Lca(int u,int v)
     {
         if(u > v)
             swap(u,v);
         )/log();
         <<k)+]])
             <<k)+]];
         return vs[dp[k][u]];//返回 u,v 的lca
     }
 }_rmq;
 //=====================================
 void Dfs(int u,int f,int d)
 {
     vs[total]=u;
     depth[total]=d;
     id[u]=total++;
     ;i < G[u].size();++i)
     {
         Node &e=G[u][i];
         if(e.to != f)
         {
             Add(total,e.w);//叶子方向,+e.w
             es[*e.id]=total;//记录朝向叶子方向的边
             Dfs(e.to,u,d+);
             vs[total]=u;
             depth[total++]=d;
             Add(total,-e.w);//根方向, -e.w
             es[*e.id+]=total;//记录朝向根方向的边
         }
     }
 }
 void Init()
 {
     _rmq.Init();
     total=;
     mem(bit,);
     ;i < maxn;++i)
         G[i].clear();
 }
 int main()
 {
     while(~scanf("%d%d%d",&n,&q,&s))
     {
         Init();
         ;i < n;++i)
         {
             int u,v;
             scanf("%d%d%d",&u,&v,w+i);
             addEdge(u,v,w[i],i);
         }
         Dfs(,-,);
         _rmq.ST();
         ;i <= q;++i)
         {
             int type;
             scanf("%d",&type);
             )
             {
                 int u;
                 scanf("%d",&u);
                 int lca=_rmq.Lca(id[u],id[s]);
                 printf(*Sum(id[lca]));
                 s=u;
             }
             else
             {
                 int x,val;
                 scanf("%d%d",&x,&val);
                 Add(es[x*],val-w[x]);//w[x] 变为 val,需要在原基础上加上 val-w[x]
                 Add(es[x*+],w[x]-val);//朝向根方向的加负值
                 w[x]=val;
             }
         }
     }
     ;
 }

RMQ+BIT

  

poj 2763(RMQ+BIT\树链剖分)的更多相关文章

  1. POJ - 2763 Housewife Wind (树链剖分/ LCA+RMQ+树状数组)

    题意:有一棵树,每条边给定初始权值.一个人从s点出发.支持两种操作:修改一条边的权值:求从当前位置到点u的最短路径. 分析:就是在边可以修改的情况下求树上最短路.如果不带修改的话,用RMQ预处理LCA ...

  2. POJ 2763 Housewife Wind (树链剖分 有修改单边权)

    题目链接:http://poj.org/problem?id=2763 n个节点的树上知道了每条边权,然后有两种操作:0操作是输出 当前节点到 x节点的最短距离,并移动到 x 节点位置:1操作是第i条 ...

  3. poj 2763 Housewife Wind : 树链剖分维护边 O(nlogn)建树 O((logn)²)修改与查询

    /** problem: http://poj.org/problem?id=2763 **/ #include<stdio.h> #include<stdlib.h> #in ...

  4. poj 2763 Housewife Wind(树链拆分)

    id=2763" target="_blank" style="">题目链接:poj 2763 Housewife Wind 题目大意:给定一棵 ...

  5. HDU 3966 & POJ 3237 & HYSBZ 2243 树链剖分

    树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...

  6. poj 3237 Tree(树链剖分,线段树)

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 7268   Accepted: 1969 Description ...

  7. POJ 3237 Tree (树链剖分)

    Tree Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 2825   Accepted: 769 Description ...

  8. POJ 2243 [SDOI2011]染色 | 树链剖分+线段树

    原题链接 肯定是树链剖分的题啦 树剖怎么做可以看我上一篇博客 如果我们已经剖完了: 然后考虑怎么维护重链和查询 用线段树维护的时候当前区间的区间颜色个数应该等于左儿子+右儿子,但是当左儿子的右端点和右 ...

  9. POJ 2763 Housewife Wind 树链拋分

    一.前言 这破题WA了一天,最后重构还是WA,最后通过POJ讨论版得到的数据显示,我看上去是把某个变量写错了..于是,还是低级错误背锅啊....代码能力有待进一步提升2333333 二.题意 某家庭主 ...

随机推荐

  1. main函数是必须的吗

    研究实验4 研究过程: 问题引出:C语言编程非得用主函数main吗,不用是否可以? 对此问题进行研究,用tc.exe书写代码如下: 图1  没有main函数的c程序 对其进行编译,链接发现,编译阶段可 ...

  2. 四则运算coding

    https://coding.net/u/ztf1641429293/p/sizeyunshuan/git/blob/master/Sizenyunsuan.java

  3. C#获取当月第一天和最后一天

    当月第一天0时0分0秒: DateTime.Now.AddDays(1 - DateTime.Now.Day).Date 当月最后一天23时59分59秒: DateTime.Now.AddDays(1 ...

  4. Spring IOP 面向切面编程

    Spring IOP  面向切面编程 AOP操作术语 Joinpoint(连接点):所谓连接点是指那些被拦截到的点.在spring中,这些点指的是方法,因为spring只支持方法类型的连接点.(类里面 ...

  5. PAT 1049 数列的片段和

    https://pintia.cn/problem-sets/994805260223102976/problems/994805275792359424 给定一个正数数列,我们可以从中截取任意的连续 ...

  6. Spring Cloud Zipkin

    Zipkin the idea is from the googlge paper:Dapper https://yq.aliyun.com/articles/60165 https://www.e4 ...

  7. multer处理post请求的代码演示

    let express = require('express'); let multer = require('multer'); let mObj = multer({dest:__dirname+ ...

  8. SQLSERVER最简单的同名数据库恢复过程.

    一. 冷备份恢复 1. net stop mssqlserver # 如果是安装的默认数据库实例 关闭 sqlserver的数据库 2. copy sqlserver的数据文件 主要是mdf 数据文件 ...

  9. 解决Ubuntu中vi命令的编辑模式下不能正常使用方向键和退格键的问题

    在Ubuntu中,进入vi命令的编辑模式,发现按方向键不能移动光标,而是会输出ABCD,以及退格键也不能正常删除字符.这是由于Ubuntu预装的是vim-tiny,而我们需要使用vim-full,解决 ...

  10. js cookies

    cookie用於識別用戶,存儲在訪問者的計算機里,當用戶首次使用瀏覽器時,會發送cookie.用戶可以創建和獲取cookie. cookie可以存儲用戶名字.用戶密碼和訪問時間等. document. ...