题意:求树上任意两点的距离

先说下欧拉序

对这颗树来说 欧拉序为 ABDBEGBACFHFCA 那欧拉序有啥用

这里先说第一个作用 求lca

对于一个欧拉序列,我们要求的两个点在欧拉序中的第一个位置之间肯定包含他们的lca,因为欧拉序1上任意两点之间肯定包含从第一个点走到第二个点访问的路径上的所有点

所以只需要记录他们的深度,然后从两个询问子节点x,y第一次出现的位置之间的深度最小值即可,可能不大好理解,看张图吧。

也就是说求lca可以转换为求一段区间的最值问题,结合rmq就可以处理啦

对于2586这题有个结论:树上任意两个点的距离等于两个点到根的距离之和减去2倍lca到根的距离

上代码

#include <cstdio>
#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
struct node
{
int x;
ll cost;
};
vector<node> edge[];
ll dis[];// 到根节点的距离
int dep[];
int ver[];// 欧拉序列
int first[];// 在欧拉序中第一次出现的位置
int vret;//
int n,m;
int mn[][];
void dfs(int x,int fa,int deep) // 求出欧拉序 以及每个点对应的度
{
ver[++vret]=x;
first[x]=vret;
dep[vret]=deep;
int len=edge[x].size();
for(int i=;i<len;i++)
{
node temp=edge[x][i];
if(temp.x!=fa)
{
dis[temp.x]=dis[x]+temp.cost;
dfs(temp.x,x,deep+);
ver[++vret]=x;
dep[vret]=deep; //
}
}
}
void st(int n)// 维护的是欧拉序 长度需要注意一下
{
int temp=(int)floor(log2(double(n)));
for(int i=;i<=n;i++) mn[i][]=i;// 注意一下 这里维护的是点 不是单纯的值
for(int j=;j<=temp;j++)
{
for(int i=;i+(<<j)-<=n;i++)
{
int a=mn[i][j-];
int b=mn[i+(<<(j-))][j-];
if(dep[a] < dep[b]) mn[i][j]=a;
else mn[i][j]=b;
}
}
}
int rmq(int x,int y)
{
int k=(int)(log(double(y-x+))/log(2.0));
int a=mn[x][k];
int b=mn[y-(<<k)+][k];
if(dep[a] < dep [b]) return a;
else return b;
}
int lca(int x,int y)
{
int fx=first[x];
int fy=first[y];
if(fx>fy) swap(fx,fy);
return rmq(fx,fy);
}
void init()
{
vret=;
dis[]=;
for(int i=;i<=n;i++) edge[i].clear();
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
init();// edge
scanf("%d %d",&n,&m);
for(int i=;i<n;i++)
{
int x,y;
ll cost;
scanf("%d %d %lld",&x,&y,&cost);
node temp;
temp.cost=cost;
temp.x=x;
edge[y].push_back(temp);
temp.x=y;
edge[x].push_back(temp);
} dfs(,,);//
st(*n-); for(int i=;i<=m;i++)
{
int x,y;
cin>>x>>y;
int temp=lca(x,y);// point
cout<<dis[x]+dis[y]-*dis[temp]<<endl;
}
}
return ;
}

hdu 2586 欧拉序+rmq 求lca的更多相关文章

  1. P3379 【模板】最近公共祖先(LCA)(欧拉序+rmq)

    P3379 [模板]最近公共祖先(LCA) 用欧拉序$+rmq$维护的$lca$可以做到$O(nlogn)$预处理,$O(1)$查询 从这里剻个图 #include<iostream> # ...

  2. lca 欧拉序+rmq(st) 欧拉序+rmq(线段树) 离线dfs 倍增

    https://www.luogu.org/problemnew/show/P3379 1.欧拉序+rmq(st) /* 在这里,对于一个数,选择最左边的 选择任意一个都可以,[left_index, ...

  3. dfs序+RMQ求LCA详解

    首先安利自己倍增求LCA的博客,前置(算不上)知识在此. LCA有3种求法:倍增求lca(上面qwq),树链剖分求lca(什么时候会了树链剖分再说.),还有,标题. 是的你也来和我一起学习这个了qwq ...

  4. HDU 2586(LCA欧拉序和st表)

    什么是欧拉序,可以去这个大佬的博客(https://www.cnblogs.com/stxy-ferryman/p/7741970.html)巨详细 因为欧拉序中的两点之间,就是两点遍历的过程,所以只 ...

  5. Bzoj 2286 & Luogu P2495 消耗战(LCA+虚树+欧拉序)

    题面 洛谷 Bzoj 题解 很容易想到$O(nk)$的树形$dp$吧,设$f[i]$表示处理完这$i$颗子树的最小花费,同时再设一个$mi[i]$表示$i$到根节点$1$路径上的距离最小值.于是有: ...

  6. dfs序和欧拉序

    生命不息,学习不止,昨天学了两个算法,总结一下,然而只是略懂,请路过的大佬多多谅解.   一.dfs序 1.什么是dfs序? 其实完全可以从字面意义上理解,dfs序就是指一棵树被dfs时所经过的节点的 ...

  7. RMQ求LCA

    题目链接 rmq求LCA,interesting. 一直没有学这玩意儿是因为CTSC的Day1T2,当时我打的树剖LCA 65分,gxb打的rmq LCA 45分... 不过rmq理论复杂度还是小一点 ...

  8. LCA-RMQ+欧拉序

    还是那一道洛谷的板子题来说吧 传送门 其实好几天之前就写了 结果dr实在是太弱了 没有那么多的精力 于是就一直咕咕咕了 哎 今天终于补上来了 LCA概念传送门 RMQ传送门 这个算法是基于RMQ和欧拉 ...

  9. BZOJ1906树上的蚂蚁&BZOJ3700发展城市——RMQ求LCA+树链的交

    题目描述 众所周知,Hzwer学长是一名高富帅,他打算投入巨资发展一些小城市. Hzwer打算在城市中开N个宾馆,由于Hzwer非常壕,所以宾馆必须建在空中,但是这样就必须建立宾馆之间的连接通道.机智 ...

随机推荐

  1. PHP课程环境安装总结文档

    phpStudy的安装 1.找一个硬盘根目录,比如这里我使用E盘,在E盘根目录创建一个php的文件夹,进入php文件夹,如下图所示 2.在步骤1的php文件夹下再建立一个文件夹php_dev,如下图所 ...

  2. python 处理geoJson to shp 互转

  3. android strings: %s、%1$s、%d、%1$d占位符

    实际开发的过程中我们有时候会遇到,一个TextView里面会遇到会有一个一大串固定的文字,而里面的数字或者个别字需要根据后台的接口而展示的.这个时候我们最简单的方法就是在string.xml文件里 使 ...

  4. js监听浏览器剪贴板

    function setClipboardText(event){ event.preventDefault(); var node = document.createElement('div'); ...

  5. 一、搭建简单的axis web服务

    转: 一.搭建简单的axis web服务 1.在官方网站下载axis的工程(这个等下就有用的)和源码.jar包等,下载地址是: http://labs.renren.com/apache-mirror ...

  6. Spring cloud微服务安全实战-6-4权限控制改造

    授权,权限的控制 令牌里的scope包含fly就有权限访问.根据Oauth的scope来做权限控制, 要让@PreAuthorize生效,就要在启动类里面写一个注解. 里面有一个属性叫做,就是在方法的 ...

  7. linux追加所有文件到新的文件(cat)

    例子如下,存在test1.txt, test2.txt, test3.txt,现在准备把这三个文件的内容都追加到testall.txt 中 test1.txt 1 2 3 4 5 6 test2.tx ...

  8. JS正则匹配邮箱格式

    观察一些邮箱格式,有些邮箱格式简单,有些复杂,在网上找了个邮箱的正则表达式,分析一下邮箱的规则.该表达式:/^\w+([\.\-]\w+)*\@\w+([\.\-]\w+)*\.\w+$/ 拆分:[1 ...

  9. 【Leetcode_easy】868. Binary Gap

    problem 868. Binary Gap solution1: class Solution { public: int binaryGap(int N) { ; vector<int&g ...

  10. 【ARTS】01_45_左耳听风-201900916~201900922

    ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 Algo ...