题意:给出一棵树,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. mybatis从dao传入多个参数到sqlmap时dao中要使用map或实例对象(如:user)作为参数传入, 否则报错找不到属性getter方法

    23:37 2015-07-02 注意1. 使用mybaits的resultMap查询时, 如果想传入多个参数(比如where 1=1动态多条件查询时)sqlmap文件中对应的方法中, selectL ...

  2. Solr + Hadoop = Big Data Love

    FROM:http://architects.dzone.com/articles/solr-hadoop-big-data-love 许多人使用Hadoop的开源项目来处理大数据的大数据集,因为它是 ...

  3. JavaScript与DOM的关系

    JavaScript与浏览器的工作 1.浏览器获取并加载你的页面,从上至下解析它的内容. 遇到JavaScript时,浏览器会解析代码,检查它的正确性,然后执行代码. 浏览器还会建立一个HTML页面的 ...

  4. XML工具类 - XmlUtils.java

    XML工具类,提供序列化XML.反序列化XML.获取指定节点的值的方法. 源码如下:(点击下载 - XmlUtils.java.dom4j-1.6.1.jar.xstream-1.4.7.jar ) ...

  5. json分别算出元素的个数和最多的元素

    个数: var str = 'aaafsdsaaasasasasaa'; var json = {}; for (var i = 0; i < str.length; i++) { if(!js ...

  6. Java 方法覆盖和方法重载

    方法重载(overloaded),要求方法的名称相同,参数列表不相同. 方法覆盖(override),要求①方法名相同,②参数列表相同,③返回值相同 如果是方法覆盖,要注意以下几种情况: 1.子类方法 ...

  7. EASYUI Dialog的基本使用

    1.基本使用 代码: <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server&q ...

  8. 李洪强漫谈iOS开发[C语言-014]-变量

    01 变量的概念 02 - 变量的语法 03 变量的使用

  9. Linux如何在虚拟机中挂载iso yum源

    首先,将作为源的iso的挂载到系统上. 代码如下: mount -o loop /dev/cdrom /mnt/iso/ 或者 mount -o loop /xxx/xxx.iso /mnt/iso/ ...

  10. ArcGIS Runtime for Android开发教程V2.0(1)基本概念

    原文地址: ArcGIS Runtime for Android开发教程V2.0(1)基本概念 - ArcGIS_Mobile的专栏 - 博客频道 - CSDN.NET http://blog.csd ...