题目

给出一棵\(n\)个点的树,从1到\(n\)编号,\(m\)次询问\({LCA} _{v\in[L,R]}\)。

\(n,m\le 3\times 10^5​\)

分析

我的做法是直接对LCA进行倍增,即\(f[i][j]\)表示从\(i\)号点开始的\(2^j\)个点的LCA,\(O(n\log ^2 n)\)预处理\(O(\log n)\)查询(分成前后两段,类似RMQ问题中ST表的做法)。

实际上还有复杂度更低的方法。

求一大堆点的共同LCA其实就是求其中dfn序最小和最大的点的LCA。直观的证明如下。取得询问点的中dfn序最小的那个,设为\(x\),另一个点\(v\)点的位置有两种情况:

  • \(v\)在\(x\)的子树内(能满足\(dfn_v>dfn_x\)),那么他们的LCA就是\(x\)
  • \(v\)在\(x\)的子树外,那么它必定在\(x\)的某一个祖先的子树内。这个祖先越往上,\(dfn_v\)就越大。

综上,一堆点的LCA为其中dfn序最小和最大的两点的LCA。

于是这个问题就变成了一个每次得到dfn序的极值点,求一次LCA的了。可以用线段树方便地实现。复杂度为\(O((n+m)\log n)\)。

代码

#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
#include<algorithm>
#define M(x) memset(x,0,sizeof x)
using namespace std;
int read() {
int x=0,f=1;
char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=3e5+1;
const int maxj=19;
int n,st[maxn][maxj],bin[maxn];
namespace tree {
vector<int> g[maxn];
int top[maxn],size[maxn],son[maxn],dep[maxn],fat[maxn];
void clear(int n) {
for (int i=1;i<=n;++i) g[i].clear();
M(top),M(size),M(son),M(dep);
}
void add(int x,int y) {g[x].push_back(y);}
int dfs(int x,int fa) {
int &sz=size[x]=1,&sn=son[x]=0;
dep[x]=dep[fat[x]=fa]+1;
for (int v:g[x]) if (v!=fa) {
sz+=dfs(v,x);
if (size[v]>size[sn]) sn=v;
}
return sz;
}
void Top(int x,int fa,int tp) {
top[x]=tp;
if (son[x]) Top(son[x],x,tp);
for (int v:g[x]) if (v!=fa && v!=son[x]) Top(v,x,v);
}
int lca(int x,int y) {
for (;top[x]!=top[y];dep[top[x]]>dep[top[y]]?x=fat[top[x]]:y=fat[top[y]]);
return dep[x]<dep[y]?x:y;
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
while (~scanf("%d",&n)) {
tree::clear(n);
for (int i=2;i<=n;++i) bin[i]=bin[i>>1]+1;
M(st);
for (int i=1;i<n;++i) {
int x=read(),y=read();
tree::add(x,y),tree::add(y,x);
}
tree::dfs(1,1);
tree::Top(1,1,1);
for (int i=1;i<=n;++i) st[i][0]=i;
for (int j=1;j<maxj;++j) for (int i=1;i<=n;++i) {
st[i][j]=st[i][j-1];
if ((i+(1<<(j-1)))<=n) st[i][j]=tree::lca(st[i][j],st[i+(1<<(j-1))][j-1]);
}
int m=read();
while (m--) {
int l=read(),r=read();
int len=r-l+1,d=bin[len];
int ans=tree::lca(st[l][d],st[r-(1<<d)+1][d]);
printf("%d\n",ans);
}
}
return 0;
}

HDU5266-pog loves szh III的更多相关文章

  1. hdu5266 pog loves szh III 【LCA】【倍增】

    Pog and Szh are playing games. Firstly Pog draw a tree on the paper. Here we define 1 as the root of ...

  2. hdu 5266 pog loves szh III(lca + 线段树)

    I - pog loves szh III Time Limit:6000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I ...

  3. HDU 5266 pog loves szh III(区间LCA)

    题目链接 pog loves szh III 题意就是  求一个区间所有点的$LCA$. 我们把$1$到$n$的$DFS$序全部求出来……然后设$i$的$DFS$序为$c[i]$,$pc[i]$为$c ...

  4. HDU 5266 pog loves szh III ( LCA + SegTree||RMQ )

    pog loves szh III Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Oth ...

  5. HDU 5266 pog loves szh III 线段树,lca

    Pog and Szh are playing games. Firstly Pog draw a tree on the paper. Here we define 1 as the root of ...

  6. HDU 5266 pog loves szh III (LCA)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5266 题目就是让你求LCA,模版题.注意dfs会栈溢出,所以要扩栈,或者用bfs写. #pragma ...

  7. HDU 5266 pog loves szh III

    题意:给出一棵树,1为根节点,求一段区间内所有点的最近公共祖先. 解法:用一棵线段树维护区间LCA.LCA是dp做法.dp[i][j]表示点i的第2^j个祖先是谁,转移方程为dp[i][j] = dp ...

  8. HDU 5266 pog loves szh III (线段树+在线LCA转RMQ)

    题目地址:HDU 5266 这题用转RMQ求LCA的方法来做的很easy,仅仅须要找到l-r区间内的dfs序最大的和最小的就能够.那么用线段树或者RMQ维护一下区间最值就能够了.然后就是找dfs序最大 ...

  9. hdu 5265 pog loves szh II

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5265 pog loves szh II Description Pog and Szh are pla ...

  10. hdu 5264 pog loves szh I

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5264 pog loves szh I Description Pog has lots of stri ...

随机推荐

  1. 20155304田宜楠-第三次作业:虚拟机的安装与Linux学习

    安装VirtualBox虚拟机 安装VirtualBox虚拟机 这一步很简单,参考老师给的教程一步步安装,很快就完成了. 2.安装Ubuntu 这一步可是让我吃尽了苦头,我按照老师给的下载地址成功下载 ...

  2. 20155320信息安全系统设计第二周课堂考试总结及myod的实现

    20155320 信息安全系统设计第二周课堂考试总结及myod的实现 第二周测试一二已在课上提交 第二周测试3-gdb测试 用gcc -g编译vi输入的代码 在main函数中设置一个行断点 在main ...

  3. 如何在存储过程的IN操作中传递字符串变量

    原始SQL如下: SELECT MONTH(OrderTime) AS datetype, SUM(DeliveryCount) AS decount, Region FROM (SELECT dbo ...

  4. 180726-InfluxDB基本概念小结

    InfluxDB基本概念小结 InfluxDB作为时序数据库,与传统的关系型数据库相比而言,还是有一些区别的,下面尽量以简单明了的方式介绍下相关的术语概念 I. 基本概念 mysql influxdb ...

  5. https双向认证网站搭建

    新建网站 在搭建网站证书之前,我们先搭建好我们的网站 1.网站基本搭建 为我们的项目新建一个网站,按照如下的步骤来 1,打开IIS,右键单击网站弹出菜单,选择网站(如图1.1.1) 图1.1.1 2, ...

  6. Linux目录与文件操作

    文件命名规则: 1.严格区分大小写: 2.长度不能超过255个字符: 3.不能使用/当文件名 mkdir:创建空目录 -p:parent,父目录,逐级创建 -v:verbose,打印详细信息 命令行展 ...

  7. TPO 03 - Architecture

    TPO 03 - Architecture Architecture is the art and science of designing structures that[主语是Architectu ...

  8. Python+MySQL开发医院网上预约系统(课程设计)一

    一:开发环境的配置 1:桌面环境为cnetos7+python2.7 2:MySQL的安装与配置 1)MySQL的安装 MySQL官方文档: http://dev.mysql.com/doc/mysq ...

  9. NO.08--VUE之自定义组件添加原生事件

    前几篇给大家分享了我的业余的“薅羊毛”的经历,回归正题,讲回vue吧: 许多vue新手在工作开发中会遇到一个问题,直接使用 button 添加原生事件是没有问题的,但是使用自定义组件添加原生事件时,就 ...

  10. Matlab中 .' 的作用。

    Syntax B = A.' B = transpose(A)   Description B = A.' returns the nonconjugate transpose of A, that ...