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 ...
随机推荐
- 20155322 2016-2017-2 《Java面向对象程序设计》第十二周课堂练习之Arrays和String单元测试
20155322 2016-2017-2 <Java面向对象程序设计>第十二周课堂练习之Arrays和String单元测试 练习目地 在IDEA中以TDD的方式对String类和Array ...
- GridView中加入//实现分页
要在GridView中加入//实现分页 AllowPaging="true" PageSize="10" // 分页时触发的事件 protectedvoid g ...
- [BZOJ3218]a + b Problem-[主席树+网络流-最小割]
Description 传送门 Solution 此处我们按最小割的思路考虑. 暴力:S->i表示该点选黑色的权值b[i]:i->T表示该点选白色的权值w[i].考虑如果某个点i受点j为白 ...
- 【LG5020】[NOIP2018]货币系统
[LG5020][NOIP2018]货币系统 题面 洛谷 题解 考场上第一眼还不会233 可以发现只要可以被其他的货币通过一些奇奇怪怪的方式表示出来的货币就\(ban\)掉即可 就是个完全背包 我是统 ...
- ios 9.1以后 添加libz.dylib 方法
1. 进入你项目的build phases 2.点击+号在弹出的对话框选择addother 3.在弹出的对话框中输入"cmd"+"shift"+"g& ...
- 数据库路由中间件MyCat - 源代码篇(15)
此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. public static void handle(String stmt, ServerConnectio ...
- javaweb(二十)——JavaBean总结
一.什么是JavaBean JavaBean是一个遵循特定写法的Java类,它通常具有如下特点: 这个Java类必须具有一个无参的构造函数 属性必须私有化. 私有化的属性必须通过public类型的方法 ...
- LUIS 语义识别API调用方法
本例使用itchat获取微信文字消息,发送给LUIS返回识别消息,再将返回消息格式化后通过微信发回 关于itchat的使用参考我的另外一篇随笔itchat个人练习 语音与文本图灵测试例程 # -*- ...
- localhost/127.0.0.1/本机IP的区别以及端口号
端口号: http请求默认的端口是:80 PHPstudy中的端口号: Apache服务器的端口是:80 MySQL数据库的端口是:3306 PHP项目端口是:9000 禅道中的端口号: Apache ...
- Jenkins Git安装设置
Jenkins Git安装设置 在此安装中,必须确保Internet连接可连接其安装 Jenkins 机器.在 Jenkins 仪表盘(主屏幕)的左侧单击 Manage Jenkins 选项.打开网址 ...