HDU 5266 bc# 43 LCA+跳表
学了一发LCA的倍增算法+跳表维护。
先说说LCA倍增算法,思路是fa[i][j]求的是i结点的2^j倍的祖先,其中2^0就是父结点了。所以可以递推fa[i][j]=fa[fa[i][j-1]][j-1]。
当求LCA时,设深度u>v,则先倍增把u提到v的同等深度,若u==v,lca就是u,否则,两点同时倍增,直到最小深度的p[u][j]!=p[v][j],此时他们的父亲p[u][0]即lca。
可以看大牛http://www.cnblogs.com/OUSUO/p/3805715.html?utm_source=tuicool,先转一发。

inline void dfs(int u)
{
int i;
for(i=head[u];i!=-1;i=next[i])
{
if (!deep[to[i]])
{
deep[to[i]] = deep[u]+1;
p[to[i]][0] = u; //p[x][0]保存x的父节点为u;
dfs(to[i]);
}
}
}

2. 初始各个点的2^j祖先是谁 ,其中2^j(j=0...log(该点深度))倍祖先,1倍祖先就是父亲,2倍祖先是父亲的父亲......。

void init()
{
int i,j;
//p[i][j]表示i结点的第2^j祖先
for(j=1;(1<<j)<=n;j++)
for(i=1;i<=n;i++)
if(p[i][j-1]!=-1)
p[i][j]=p[p[i][j-1]][j-1];//i的第2^j祖先就是i的第2^(j-1)祖先的第2^(j-1)祖先
}


int lca(int a,int b)//最近公共祖先
{
int i,j;
if(deep[a]<deep[b])swap(a,b);
for(i=0;(1<<i)<=deep[a];i++);
i--;
//使a,b两点的深度相同
for(j=i;j>=0;j--)
if(deep[a]-(1<<j)>=deep[b])
a=p[a][j];
if(a==b)return a;
//倍增法,每次向上进深度2^j,找到最近公共祖先的子结点
for(j=i;j>=0;j--)
{
if(p[a][j]!=-1&&p[a][j]!=p[b][j])
{
a=p[a][j];
b=p[b][j];
}
}
return p[a][0];
}

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std; const int N=300010; struct Edge{
int v,next;
}edge[N*2];
int head[N],tot;
int fa[N][22],dp[N][22];
int dep[N]; void addedge(int u,int v){
edge[tot].v=v;
edge[tot].next=head[u];
head[u]=tot++;
} void BFS(int rt){
queue<int>que;
que.push(rt);
fa[rt][0]=-1; dep[rt]=1;
while(!que.empty()){
int u=que.front();
que.pop();
for(int i=1;i<=20;i++){
if(fa[u][i-1]!=-1){
fa[u][i]=fa[fa[u][i-1]][i-1];
}
}
for(int e=head[u];e!=-1;e=edge[e].next){
int v=edge[e].v;
if(dep[v]==0){
dep[v]=dep[u]+1;
fa[v][0]=u;
que.push(v);
}
}
}
} int LCA(int u,int v){
int i,j;
if(dep[u]<dep[v])swap(u,v);
for(i=0;(1<<i)<=dep[u];i++);
i--;
for(j=i;j>=0;j--){
if(dep[u]-(1<<j)>=dep[v])
u=fa[u][j];
}
if(u==v) return u;
for(j=i;j>=0;j--){
if(fa[u][j]!=-1&&fa[u][j]!=fa[v][j]){
u=fa[u][j];
v=fa[v][j];
}
}
return fa[u][0];
} int main(){
int n,q,u,v;
while(scanf("%d",&n)!=EOF){
memset(head,-1,sizeof(head));
tot=0;
memset(fa,-1,sizeof(fa));
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
memset(dep,0,sizeof(dep));
BFS(1);
// cout<<LCA(1,5)<<endl;
// cout<<LCA(2,3)<<endl;
for(int i=1;i<=n;i++)
dp[i][0]=i;
for(int j=1;j<=20;j++){
for(int i=1;i+(1<<j)-1<=n;i++)
dp[i][j]=LCA(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
/* for(int i=1;i<=n;i++){
for(int j=0;j<=6;j++)
cout<<dp[i][j]<<" ";
cout<<endl;
}*/
scanf("%d",&q);
while(q--){
scanf("%d%d",&u,&v);
// if(u>v) swap(u,v);
if(u==v)
printf("%d\n",u);
else{
int ans=u;
for(int i=20;i>=0;i--){
if(u+(1<<i)-1<=v){
ans=LCA(ans,dp[u][i]);
u=u+(1<<i);
}
}
printf("%d\n",ans);
}
}
}
return 0;
}
HDU 5266 bc# 43 LCA+跳表的更多相关文章
- 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 + 线段树)
I - pog loves szh III Time Limit:6000MS Memory Limit:131072KB 64bit IO Format:%I64d & %I ...
- skiplist 跳表(1)
最近学习中遇到一种新的数据结构,很实用,搬过来学习. 原文地址:skiplist 跳表 为什么选择跳表 目前经常使用的平衡数据结构有:B树,红黑树,AVL树,Splay Tree, Treep等. ...
- SkipList跳表基本原理
为什么选择跳表 目前经常使用的平衡数据结构有:B树,红黑树,AVL树,Splay Tree, Treep等. 想象一下,给你一张草稿纸,一只笔,一个编辑器,你能立即实现一颗红黑树,或者AVL树 出来吗 ...
- 算法进阶面试题06——实现LFU缓存算法、计算带括号的公式、介绍和实现跳表结构
接着第四课的内容,主要讲LFU.表达式计算和跳表 第一题 上一题实现了LRU缓存算法,LFU也是一个著名的缓存算法 自行了解之后实现LFU中的set 和 get 要求:两个方法的时间复杂度都为O(1) ...
- 数据结构笔记之跳表(SkipList)
一.跳表简述 跳表可以看做是一个带有索引的链表,在介绍跳表之前先看一下一个普通的链表,假如当前维护了一个有序的链表: 现在要在这个链表中查找128,因为事先不知道链表中数值的分布情况,我们只能从前到后 ...
- C语言跳表(skiplist)实现
一.简介 跳表(skiplist)是一个非常优秀的数据结构,实现简单,插入.删除.查找的复杂度均为O(logN).LevelDB的核心数据结构是用跳表实现的,redis的sorted set数据结构也 ...
- K:跳表
跳表(SkipList)是一种随机化的数据结构,目前在redis和leveldb中都有用到它,它的效率和红黑树以及 AVL 树不相上下,但跳表的原理相当简单,只要你能熟练操作链表, 就能轻松实现一 ...
- SkipList跳表(一)基本原理
一直听说跳表这个数据结构,说要学一下的,懒癌犯了,是该治治了 为什么选择跳表 目前经常使用的平衡数据结构有:B树.红黑树,AVL树,Splay Tree(这个树好像还没有听说过),Treep(也没有听 ...
随机推荐
- js 调用微信浏览器内置方法,启动支付
$.post("{php echo app_url('pay/cash')}",{orderno:orderno,paytype:paytype},function(m){ //t ...
- WIN 10家庭版没有Hyper-V
新建文件Hyper-V.cmd 内容如下 pushd "%~dp0"dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum > ...
- C语言常量
Constant包括4种类型: 整型 浮点型 枚举 字符型 #include <stddef.h> #include <uchar.h> int main() { /* Int ...
- iOS CoreData 开发之数据模型关系
接着上一篇,上一篇中,我们简单的实现了一个用户实体,本次添加一个用户信息实体,与用户实体相关联,关系为1:1. 新建一个实体UserInfo:
- Android开发笔记(9)——初步设置Menu
转载请注明:http://www.cnblogs.com/igoslly/p/6858656.html 初步设置Menu 设置Menu,在ActionBar上添加按钮操作: 在 ...
- html5——多媒体(一)
<audio> 1.autoplay 自动播放 2.controls 是否显不默认播放控件 3.loop 循环播放 4.preload 预加载 同时设置autoplay时些属性失效 5.由 ...
- 03--QT教程(转自:豆子)
http://blog.51cto.com/zt/20
- 【sqli-labs】 less47 GET -Error based -String -Order By Clause(GET型基于错误的字符型Order By从句注入)
http://192.168.136.128/sqli-labs-master/Less-47/?sort=1 改变sort的值,结果仍然是order by 1的结果 http://192.168.1 ...
- graphite 绘图工具
graphite 绘图工具
- 扩增子图表解读3热图:差异菌、OTU及功能
热图是使用颜色来展示数值矩阵的图形.通常还会结合行.列的聚类分析,以表达实验数据多方面的结果. 热图在生物学领域应用广泛,尤其在高通量测序的结果展示中很流行,如样品-基因表达,样品-OTU相对丰度矩 ...