HDU6031:Innumerable Ancestors(二分+倍增数组)
传送门
题意
n个点的图,有n-1条无向边,m个询问,每次询问
给出两个集合a和b,找到a的一个元素x,b的一个元素y,使得x和y的lca深度最大
分析
这道题如果直接暴力做,复杂度为O(mk1k2*n),爆掉
考虑二分lca的深度,那么进行如下处理,对于深度deep,如果两个集合(a存在元素x,b存在元素y),使得x向上走depth[x]-deep次与y向上走depth[y]-deep次走到的点相同,那么该深度满足条件。具体做法:
1.统计a数组中每个点向上走depth[i]-deep次到达的点,放入集合中
2.查询b数组中是否存在点向上走depth[i]-deep次到达集合中的点
有则返回true,否则返回false
代码
#include<cstdio>
#include<cstring>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
int n,m,k1,k2,a[100100],b[100100];
vector<int>mp[100100];
#define F(i,a,b) for(int i=a;i<=b;++i)
#define mem(a,b) memset(a,b,sizeof(a))
int fa[100100],up[100100][20],depth[100100];
void dfs(int u,int pre,int deep)//遍历,标记父亲,深度
{
fa[u]=pre;
depth[u]=deep;
int num=mp[u].size();
F(i,0,num-1)if(mp[u][i]!=pre)
{
dfs(mp[u][i],u,deep+1);
}
}
void init()//构建后缀数组
{
F(i,1,n) up[i][0]=fa[i];
F(j,1,19)F(i,1,n) up[i][j]=up[up[i][j-1]][j-1];
}
int judge(int a,int deep)//返回a的deep深度的祖先
{
if(deep<0) return -1;
if(deep==0) return a;
for(int i=19;i>=0;--i) if(deep&(1<<i))
{
a=up[a][i];
}
return a;
}
int check(int deep)//判断该深度两个集合是否存在深度相同的两个点
{
set<int>s;
F(i,1,k1)//记录该深度下所有祖先
{
int ret=depth[a[i]]-deep;
int anc=judge(a[i],ret);
if(anc==-1) continue;
s.insert(anc);
}
F(i,1,k2)//在数组b中找到相同深度下是否存在相同祖先
{
int ret=depth[b[i]]-deep;
int anc=judge(b[i],ret);
if(anc==-1) continue;
if(s.count(anc)) return 1;
}
return 0;
}
int main()
{
while(scanf("%d %d",&n,&m)!=EOF)
{
int u,v;
F(i,1,n) mp[i].clear();
F(i,1,n-1)//建图
{
scanf("%d %d",&u,&v);
mp[u].push_back(v);
mp[v].push_back(u);
}
dfs(1,0,0);
init();
F(i,1,m)
{
int l=1,r=1,ans=0;
scanf("%d",&k1);
//printf("%d\n",n);
//F(i,1,n) printf("%d%c",depth[i],i==n?'\n':' ');
F(i,1,k1) {scanf("%d",a+i);r=max(depth[a[i]],r);}
//puts("flag");
scanf("%d",&k2);
F(i,1,k2) scanf("%d",b+i);
while(l<=r)//二分深度
{
int mid=(l+r)>>1;
if(check(mid)) { ans=mid;l=mid+1; }else r=mid-1;
}
printf("%d\n",ans+1);
}
}
return 0;
}
HDU6031:Innumerable Ancestors(二分+倍增数组)的更多相关文章
- HDU-6031 Innumerable Ancestors(二分+树上倍增)
题意 给一棵树,$m$次询问,每次询问给两个点集问从两个点集中各取一个点的$LCA$的最大深度. 思路 二分答案.对于某个二分过程中得到的$Mid$,如果可行则两个点集在$Mid$所在的深度存在公共的 ...
- HDU6031 Innumerable Ancestors 倍增 - 题意详细概括 - 算法详解
去博客园看该题解 题目 查看原题 - HDU6031 Innumerable Ancestors 题目描述 有一棵有n个节点的有根树,根节点为1,其深度为1,现在有m个询问,每次询问给出两个集合A和B ...
- POJ.1330 Nearest Common Ancestors (LCA 倍增)
POJ.1330 Nearest Common Ancestors (LCA 倍增) 题意分析 给出一棵树,树上有n个点(n-1)条边,n-1个父子的边的关系a-b.接下来给出xy,求出xy的lca节 ...
- JZYZOJ1454 NOIP2015 D2T3_运输计划 二分 差分数组 lca tarjan 树链剖分
http://172.20.6.3/Problem_Show.asp?id=1454 从这道题我充分认识到我的脑子里好多水orz. 如果知道了这个要用二分和差分写,就没什么思考上的难点了(屁咧你写了一 ...
- 【bzoj2280】[Poi2011]Plot 二分+倍增+二分+最小圆覆盖
题目描述 给出一系列点p_1, p_2, ... , p_n,将其分成不多余m个连续的段,第i段内求一个点q_i,使得q_i到这段内点的距离的最大值的最大值最小 输入 第一行,n m下面n行,每行两个 ...
- 51nod 1105 第K大的数 【双重二分/二分套二分/两数组任意乘积后第K大数】
1105 第K大的数 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 收藏 关注 数组A和数组B,里面都有n个整数.数组C共有n^2个整数,分别是A[0] * ...
- 洛谷 P1083 [ NOIP 2012 ] 借教室 —— 线段树 / 二分差分数组
题目:https://www.luogu.org/problemnew/show/P1083 当初不会线段树的时候做这道题...对差分什么不太熟练,一直没A,放在那儿不管... 现在去看,线段树就直接 ...
- BZOJ 2946 [Poi2000]公共串 (二分+Hash/二分+后缀数组/后缀自动机)
求多串的最长公共字串. 法1: 二分长度+hash 传送门 法2: 二分+后缀数组 传送门 法3: 后缀自动机 拿第一个串建自动机,然后用其他串在上面匹配.每次求出SAM上每个节点的最长匹配长度后,再 ...
- LeetCode 81,在不满足二分的数组内使用二分法 II
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode专题第50篇文章,我们来聊聊LeetCode中的81题Search in Rotated Sorted ArrayII ...
随机推荐
- UltraEdit UE常见问题 使用必读
1 UE设置出多个tag标签,能切换的那种样子 现在的现象就是图上显示的样子,我想弄出来多个标签能切换的样子,就像浏览器的多个标签那样,怎么操作呢 视图->视图/列表->打开文件标签可以使 ...
- 删除DataGridView选中行并更新数据库
前面写过一篇文章是DataGridView控件显示数据的,DataGridView在与数据库打交道时会常常出现,也非常有用.通过DataGridView对数据库进行更改和查询都比較方便. 这里我们须要 ...
- js 类继承extends
先看例子: <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <titl ...
- Indri和Terrier搜索引擎的使用
介绍 Indri和Terrier都是开源的搜索引擎,当中Indri作为Lemur项目的一个重要部分,具有强大的查询接口,易建索引,可扩展,高效率等长处.能够在SourceForge Lemur Pro ...
- Using Virtual Serial Ports on Linux (Ubuntu)
http://www.xappsoftware.com/wordpress/2013/10/07/using-virtual-serial-ports-on-linux-ubuntu/?goback= ...
- Codeforces Round #253 (Div. 2)——Borya and Hanabi
题目连接 题意: n表示有n个卡片.每一个卡片有一种颜色和一个数字(共五种不同的颜色和五个不同的数字). 事先知道每种卡片有几张.可是不知道详细的位置. 问须要几次提示就能够知道全部卡片的位置都在哪里 ...
- 甘特图——Excel搞定
1. 甘特图 概念 甘特图就是条形图的一种. 甘特图是基于作业排序的目的,将活动与时间联系起来的最早尝试之中的一个. 这是什么意思呢?也就是说甘特图用来表示什么时间做什么事情,相当于一个计划安排.并且 ...
- asp对中文编码及解码,Decode和Encode中文网址处理
<%'-------------------------------------------------------------------------- '================== ...
- configuration类详解
hadoop中,组件配置是由Hadoop的Configuration的一个实例实现.(在源码包的org.apache.hadoop.conf中可以找到)先上个类图:这只是部分的,Configuraat ...
- 20170218 OO-ALV标准工具栏按钮
原文地址:OO ALV 工具栏对于的功能码 图标与对应的 功能码 明细 &DETAIL 检查 &CHECK 刷新 &REFRESH 剪切 &LOCAL&CU ...