HDU 5266 pog loves szh III
题意:给出一棵树,1为根节点,求一段区间内所有点的最近公共祖先。
解法:用一棵线段树维护区间LCA。LCA是dp做法。dp[i][j]表示点i的第2^j个祖先是谁,转移方程为dp[i][j] = dp[dp[i][j - 1]][j - 1],初始的dp[i][0]可以用一次dfs求得,这样可以用logn的时间求第x个祖先或查询LCA。求第x个祖先可以从二进制的角度理解,假设x是10,转化为二进制是1010,那么只要升2^3 + 2^1个深度就可以求出第x个祖先。求LCA的具体做法是,先将点a和b升至同一深度,如果此时a和b为同一个点,说明LCA就是a(或者b),如果不是同一个点,再同时向上升,直到已经无法找到两个点的祖先是不同点,说明两个点已经升至LCA的下一层,再向上升一层即为LCA。
然后就是建一棵线段树,只需要查询,没有更新,查询的写法纠结了好久……
因为代码写的太屎了,扩栈了依然会RE……所以只好用栈模拟……但是不扩栈又会T……不太理解那句扩栈用的语句的原理TUT……5000+ms擦边过了……
代码:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<math.h>
#include<limits.h>
#include<time.h>
#include<stdlib.h>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define LL long long
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#pragma comment(linker, "/STACK:10240000000,10240000000")
using namespace std;
vector <int> tree[300005];
bool vis[300005];
int deep[300005];
int dp[300005][30];
int st[300005 << 2];
struct node
{
int rt, dep;
node(int rt, int dep) : rt(rt), dep(dep) {}
node() {}
};
stack <node> s;
int LCA(int a, int b)
{
if(deep[a] < deep[b])
swap(a, b);
for(int i = 20; i >= 0; i--)
{
if(deep[a] == deep[b])
break;
if(deep[dp[a][i]] >= deep[b])
a = dp[a][i];
}
if(a == b)
return a;
for(int i = 20; i >= 0; i--)
{
if(dp[a][i] != dp[b][i])
{
a = dp[a][i];
b = dp[b][i];
}
}
return dp[a][0];
}
void pushUp(int rt)
{
st[rt] = LCA(st[rt << 1], st[rt << 1 | 1]);
}
void build(int l, int r, int rt)
{
if(l == r)
{
st[rt] = l;
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
pushUp(rt);
}
int query(int ll, int rr, int l, int r, int rt)
{
if(ll <= l && rr >= r)
return st[rt];
int m = (l + r) >> 1;
int res;
if(ll <= m)
{
res = query(ll, rr, lson);
if(rr > m)
return LCA(res, query(ll, rr, rson));
else
return res;
}
else
return query(ll, rr, rson);
}
int main()
{
int n;
while(~scanf("%d", &n))
{
for(int i = 0; i < 300005; i++)
tree[i].clear();
for(int i = 0; i < n - 1; i++)
{
int a, b;
scanf("%d%d", &a, &b);
tree[a].push_back(b);
tree[b].push_back(a);
}
memset(vis, 0, sizeof vis);
memset(dp, 0, sizeof dp);
vis[1] = true;
dp[1][0] = 1;
s.push(node(1, 1));
while(!s.empty())
{
node top = s.top();
deep[top.rt] = top.dep;
int len = tree[top.rt].size();
int flag = true;
for(int i = 0; i < len; i++)
{
if(!vis[tree[top.rt][i]])
{
vis[tree[top.rt][i]] = true;
dp[tree[top.rt][i]][0] = top.rt;
s.push(node(tree[top.rt][i], top.dep + 1));
flag = false;
}
}
if(flag)
s.pop();
}
for(int j = 1; j < 20; j++)
{
for(int i = 1; i <= n; i++)
{
dp[i][j] = dp[dp[i][j - 1]][j - 1];
}
}
build(1, n, 1);
int q;
scanf("%d", &q);
for(int i = 0; i < q; i++)
{
int a, b;
scanf("%d%d", &a, &b);
printf("%d\n", query(a, b, 1, n, 1));
}
}
return 0;
}
HDU 5266 pog loves szh III的更多相关文章
- 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转RMQ)
题目地址:HDU 5266 这题用转RMQ求LCA的方法来做的很easy,仅仅须要找到l-r区间内的dfs序最大的和最小的就能够.那么用线段树或者RMQ维护一下区间最值就能够了.然后就是找dfs序最大 ...
- 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 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 ...
- hdu 5264 pog loves szh I 水题
pog loves szh I Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?p ...
随机推荐
- NET Reflector 8 使用
一,把杀毒软件停掉 二,把原机器上的 Reflector 文件删除 三,找到C:\Users\Administrator\AppData\Local\Red Gate这个目录,将里面的东西删除 四,v ...
- 【BZOJ 1067】 [SCOI2007]降雨量
Description 我们常常会说这样的话:“X年是自Y年以来降雨量最多的”.它的含义是X年的降雨量不超过Y年,且对于任意Y<Z<X,Z年的降雨量严格小于X年.例如2002,2003,2 ...
- how to get sharepoint lookup value
SPFieldLookup lookUp1 = properties.ListItem.ParentList.Fields.GetField("Leave_x0020_Type") ...
- Increase SharePoint Execution Timeout
<system.web> <compilation batch="false" batchTimeout="600" maxBatchSize ...
- My97DatePicker{js日历插件}
VS自带了一个日历控件:Calendar,但是它有一个缺陷:即在选择,隐藏,显示的时候都会引起回传 Calendar控件的一些用法: 取值:Calendar1.SelectedDate.ToSh ...
- 第三方登录过程—OAuth2.0协议
---恢复内容开始--- 理清思路 1.在第三方注册成为开发者,拿到第三方给的client_id(app_id---就像你的身份证.QQ号)和client_secret(就像你的QQ密码): 2.填写 ...
- java第四课:数组
1.数组声明时,必须有中括号,但不指定数组的元素个数2.初始化时,必须指定元素个数3.数组元素内容仅能用于声明时初始化,不能用于赋值.如:char[] week; week={'1','2','3'} ...
- HZNU1015: 矩阵排序
http://acm.hznu.edu.cn/JudgeOnline/problem.php?id=1015 题意:把矩阵每一行都排序. (以前觉得很难的题目回头看看原来如此简单 ][]; ; i&l ...
- Hadoop将过时了?
http://www.kuqin.com/database/20120715/322528.html Hadoop这个单词如今铺天盖地,几乎成了大数据的代名词.仅仅数年时间,Hadoop从边缘技术迅速 ...
- Unix/Linux下如何使用Vi编辑器
vi 的工作模式 Vi 在初始启动后首先进入编辑模式,这时用户可以利用一些预先定义的按键来移动光标.删除文字. 复制或粘贴文字等.这些按键均是普通的字符,例如 l 是向右移动光标,相当于向右箭头键,k ...