传送门

题意

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(二分+倍增数组)的更多相关文章

  1. HDU-6031 Innumerable Ancestors(二分+树上倍增)

    题意 给一棵树,$m$次询问,每次询问给两个点集问从两个点集中各取一个点的$LCA$的最大深度. 思路 二分答案.对于某个二分过程中得到的$Mid$,如果可行则两个点集在$Mid$所在的深度存在公共的 ...

  2. HDU6031 Innumerable Ancestors 倍增 - 题意详细概括 - 算法详解

    去博客园看该题解 题目 查看原题 - HDU6031 Innumerable Ancestors 题目描述 有一棵有n个节点的有根树,根节点为1,其深度为1,现在有m个询问,每次询问给出两个集合A和B ...

  3. POJ.1330 Nearest Common Ancestors (LCA 倍增)

    POJ.1330 Nearest Common Ancestors (LCA 倍增) 题意分析 给出一棵树,树上有n个点(n-1)条边,n-1个父子的边的关系a-b.接下来给出xy,求出xy的lca节 ...

  4. JZYZOJ1454 NOIP2015 D2T3_运输计划 二分 差分数组 lca tarjan 树链剖分

    http://172.20.6.3/Problem_Show.asp?id=1454 从这道题我充分认识到我的脑子里好多水orz. 如果知道了这个要用二分和差分写,就没什么思考上的难点了(屁咧你写了一 ...

  5. 【bzoj2280】[Poi2011]Plot 二分+倍增+二分+最小圆覆盖

    题目描述 给出一系列点p_1, p_2, ... , p_n,将其分成不多余m个连续的段,第i段内求一个点q_i,使得q_i到这段内点的距离的最大值的最大值最小 输入 第一行,n m下面n行,每行两个 ...

  6. 51nod 1105 第K大的数 【双重二分/二分套二分/两数组任意乘积后第K大数】

    1105 第K大的数  基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 数组A和数组B,里面都有n个整数.数组C共有n^2个整数,分别是A[0] * ...

  7. 洛谷 P1083 [ NOIP 2012 ] 借教室 —— 线段树 / 二分差分数组

    题目:https://www.luogu.org/problemnew/show/P1083 当初不会线段树的时候做这道题...对差分什么不太熟练,一直没A,放在那儿不管... 现在去看,线段树就直接 ...

  8. BZOJ 2946 [Poi2000]公共串 (二分+Hash/二分+后缀数组/后缀自动机)

    求多串的最长公共字串. 法1: 二分长度+hash 传送门 法2: 二分+后缀数组 传送门 法3: 后缀自动机 拿第一个串建自动机,然后用其他串在上面匹配.每次求出SAM上每个节点的最长匹配长度后,再 ...

  9. LeetCode 81,在不满足二分的数组内使用二分法 II

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode专题第50篇文章,我们来聊聊LeetCode中的81题Search in Rotated Sorted ArrayII ...

随机推荐

  1. window7_64安装STAF

    1.       安装包下载 从http://sourceforge.net/projects/staf/files/staf/V3.4.17/下载所需安装包,有Windows.Linux.Solar ...

  2. Solidworks打印工程图超出范围了怎么办

    打印预览,边框部分无法显示   页面设置,比例改为90%,试一下   正常了,如果你还是无法正常显示,就再改小比例

  3. 重装系统(Win)

    有朋友问我,重装系统该怎样操作呢? 1. 硬盘重装 官网:http://www.heiyunwang.com/ ,点击下载软件:http://dlsw.baidu.com/sw-search-sp/s ...

  4. linux 进程间通信之 消息队列

    消息队列就是一个消息的链表. 能够把消息看作一个记录,具有特定的格式以及特定的优先级.对消息队列有写权限的进程能够向中依照一定的规则加入新消息.有读权限的进程则能够读走消息. 读走就没有了.消息队列是 ...

  5. android 编程小技巧(持续中)

    first:     Intent跳转一般存用于Activity类,可是若要在非activity类里跳转的话,解决方法是在startActivity(intent)前加mContext即上下文,终于为 ...

  6. javascript模块化编程:CommonJS和AMD规范

    AMD规范,异步模块定义.与CommonJS规范齐名并列. 作用都是利于JavaScript的模块化编程. 模块化编程的好处就是: 1.可重用 2.独立 3.能解决加载的依赖性问题 4.能解决重复加载 ...

  7. Quartz -第一篇-入门

    学习地址:https://www.imooc.com/learn/846 官网:www.quartz-scheduler.org 特点:分布式+集群 设计模式: 工厂模式 builder模式 组件模式 ...

  8. Nhibernate开发中遇见的问题列表

    1.No persister for: LantrackCommon.pentity.BASESTANDARD 解答修改方法:我的是因为映射关系文件在属性里的生成操作设置成:嵌入的资源.

  9. Echarts饼状图

    <head> <meta charset="utf-8"> <title>ECharts</title> <script sr ...

  10. UISwitch用法:

    代码: #import "ViewController.h" @interface ViewController () @end @implementation ViewContr ...