传送门

题意

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. python 学习笔记 13 -- 经常使用的时间模块之time

    Python 没有包括相应日期和时间的内置类型.只是提供了3个相应的模块,能够採用多种表示管理日期和时间值: *    time 模块由底层C库提供与时间相关的函数.它包括一些函数用于获取时钟时间和处 ...

  2. Youth is not a time of life, it is a state of mind.

    青春不是生命的一段,而是一种精神状态.

  3. 重新认识一遍JavaScript

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. node 爬虫 --- 将爬取到的数据,保存到 mysql 数据库中

    步骤一:安装必要模块 (1)cheerio模块 ,一个类似jQuery的选择器模块,分析HTML利器. (2)request模块,让http请求变的更加简单 (3)mysql模块,node连接mysq ...

  5. 8. Smarty3:模版中的内置函数

    smarty3中对内置函数的修改比較大,加入了很多新的功能:变量声明.表达式,流程控制,函数.数组等.可是建议不要在模版中去使用过于复杂的逻辑,而是要尽量将一些程序设计逻辑写到PHP中,并在模版中採用 ...

  6. hiberinate二级缓存

    hibernate.cfg.xml配置 <!-- 二级缓存类型 --> <property name="hibernate.cache.region.factory_cla ...

  7. 项目记录26--unity-tolua框架 View03-UIManager.lua

    做为程序员要懂得假设保持健康,对电脑时间太长非常easy眼花,得脖子病,腰都疼,这星期六日组团到康宁去了,哈哈. 一个字"疼"!!!! 废话不多少,把UIManager.lua个搞 ...

  8. 【转载】FAT12格式的引导程序(2)

     1.用WinImage来写入到引导区的详细步骤: 启动WinImage后,打开“文件”菜单,单击菜单中的“打开”命令. 选择之前保存的磁盘镜像文件“boot.img”或者“boot.ima”. 打开 ...

  9. Python开发【深浅拷贝】

    1.==与is a = [1,2] b = [1,2] a==b >>>True a is b >>>False 2.拷贝与非拷贝 拷贝:原则上就是把数据分离出来, ...

  10. effctive C++ 读书笔记 条款 16

    条款16 成对使用new和delete时要採取同样形式 #include <iostream> #include <string> using namespace std; / ...