题意:给出一棵树,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的更多相关文章

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

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

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

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

  3. 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 ...

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

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

  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 5265 pog loves szh II

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

  8. 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 ...

  9. 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 ...

随机推荐

  1. [SQL SERVER系列]读书笔记之SQL注入漏洞和SQL调优

    最近读了程序员的SQL金典这本书,觉得里面的SQL注入漏洞和SQL调优总结得不错,下面简单讨论下SQL注入漏洞和SQL调优. 1. SQL注入漏洞 由于“'1'='1'”这个表达式永远返回 true, ...

  2. ADO.net--杂七杂八(一)

    private void BtnConnectDataBase_Click(object sender, RoutedEventArgs e) { string connectionString = ...

  3. JAVA面试题:equals()方法和== 区别

    http://bbs.csdn.net/topics/390000725 总结: equals在没重写之前和==一样,重写之后,equals只要内容一样即为true equals跟==一般情况下是等价 ...

  4. linux查看历史命令history

    在linux下,我们有可能需要查看最近执行过的命令(历史命令),我们可以进行如下操作: # 显示使用过的所有历史命令 $ history # 显示最近使用的5个命令 $ history 5 我们可以通 ...

  5. BZOJ 4003 JLOI2015 城池攻占

    做法和APIO2012派遣 那道题目类似 在树上DFS,维护当前子树的小根堆 因为需要合并孩子们的信息,使用左偏树就可以了 每次弹出死亡骑士,对剩余骑士打上奖励标记 至于标记的下传和更改,只需要每次在 ...

  6. WPF之小动画二

    上一篇文章简单介绍了动画的定义方法和一些控制动画的方法,并没有涉及复杂属性的动画处理方式,本文将继续动画的其它方面的使用. 写在前面(对于一些动画操作时候的建议): 1.如果希望某个元素从显示到消失, ...

  7. Android Editext监听光标位置

    因为项目需要,需要实时监听光标的位置变化,网上提出的用TextWatcher和onTouchListener中调用contentText.getSelectionStart()都是获取的上一次位置. ...

  8. JDK个目录,以及与环境变量的关系

    最近学习过程中老是看JDK里面的东西,可每次都翻书找,找了又忘.JDK,我们今天来个了断吧........ 一:bin: JDK中所包含的开发工具的可执行文件,PATH环境变量应该包含一个指向此目录的 ...

  9. 如何提高Web服务端并发效率的异步编程技术

    作为一名web工程师都希望自己做的web应用能被越来越多的人使用,如果我们所做的web应用随着用户的增多而宕机了,那么越来越多的人就会变得越来越少了,为了让我们的web应用能有更多人使用,我们就得提升 ...

  10. sed awk 要获得每行的最后一个逗号后边的内容

    获得每行的最后一个逗号后边的内容.例如:KIAA1967 KIAA1967, xxxxSECIS biding proin 2-like, SECISBP2L, yyyy 1234ankyrin re ...