HDU5266-pog loves szh III
题目
给出一棵\(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的更多相关文章
- 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 ...
- hdu 5266 pog loves szh III(lca + 线段树)
I - pog loves szh III Time Limit:6000MS Memory Limit:131072KB 64bit IO Format:%I64d & %I ...
- HDU 5266 pog loves szh III(区间LCA)
题目链接 pog loves szh III 题意就是 求一个区间所有点的$LCA$. 我们把$1$到$n$的$DFS$序全部求出来……然后设$i$的$DFS$序为$c[i]$,$pc[i]$为$c ...
- 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 ...
- 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 ...
- HDU 5266 pog loves szh III (LCA)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5266 题目就是让你求LCA,模版题.注意dfs会栈溢出,所以要扩栈,或者用bfs写. #pragma ...
- HDU 5266 pog loves szh III
题意:给出一棵树,1为根节点,求一段区间内所有点的最近公共祖先. 解法:用一棵线段树维护区间LCA.LCA是dp做法.dp[i][j]表示点i的第2^j个祖先是谁,转移方程为dp[i][j] = dp ...
- HDU 5266 pog loves szh III (线段树+在线LCA转RMQ)
题目地址:HDU 5266 这题用转RMQ求LCA的方法来做的很easy,仅仅须要找到l-r区间内的dfs序最大的和最小的就能够.那么用线段树或者RMQ维护一下区间最值就能够了.然后就是找dfs序最大 ...
- 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 ...
- 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 ...
随机推荐
- 20155310第一周JAVA实验报告
20155310第一周JAVA实验报告 实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用Eclipse 编辑.编译.运行.调试Java程序. 实验要求 使用JDK和IDE编译.运行简单 ...
- win10 64位redis的安装和测试
步骤记录: 1.官网没有redis64位的版本,在git开源项目上找到64位的可用版本 https://www.cnblogs.com/tommy-huang/p/6093813.html 这里有下载 ...
- MySQL入门篇(二)之常见命令管理
一.SQL结构化查询语言 SQL,英文全称Structured Query Language,中文意思是结构化查询语言.它是一种对关系数据库中的数据进行定义和操作的语言方法,是大多数关系数据库管理系统 ...
- 9.15 DP合集水表
9.15 DP合集水表 显然难了一些啊. 凸多边形的三角剖分 瞄了一眼题解. 和蛤蛤的烦恼一样,裸的区间dp. 设f[i][j]表示i~j的点三角剖分最小代价. 显然\(f[i][i+1]=0,f[i ...
- Karma与TSLint
TSLint TSLint是一个可扩展的静态分析工具,用于检查TypeScript代码的可读性,可维护性和功能性错误.收到现代编辑和构建系统的广泛支持,并且可以使用您自己的路由,配置和格式化. 安装 ...
- TPO 02 - The Origins of Cetaceans
TPO 02 - The Origins of Cetaceans It should be obvious that cetaceans[n. 鲸目动物]-whales, porpoises [n. ...
- python终端计算器,还有没其他方法?
import sysdef lt(a, b, c ): if b == "+": return int(a)+int(c) elif b == "-": ret ...
- Qt 链接报错 version `Qt_5' not found
问题: 在Ubuntu 上发布软件包的时候,复制链接库的时候出现Qt 版本找不到的情况: ./libqxcb.so: /usr/lib/x86_64-linux-gnu/libQt5XcbQpa.so ...
- 设计模式C++实现(1)——策略(Strategy)模式
目录 策略模式 应用案例 实现的关键 Talk is cheap,let's See The Code 设计思想 参考 策略模式 策略模式定义了一系列算法和行为(也就是策略),他们可以在运行时相互替换 ...
- PIGCMS 关闭聊天机器人(小黄鸡)
无脑操作举例 1.找到 WeixinAction.class.php 文件,路径: 你的版本\PigCms\Lib\Action\Home 2.查询 function chat ,在 chat() 函 ...