传送门

题意

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. [WASM Rust] Create and Publish a NPM Package Containing Rust Generated WebAssembly using wasm-pack

    wasm-pack is a tool that seeks to be a one-stop shop for building and working with Rust generated We ...

  2. SolidEdge如何自动标注尺寸

    1 工具-尺寸-关系助手(必须在编辑草图轮廓状态下,如果你的草图不可编辑,则没有这些选项)   2 框选要自动标注尺寸的东西,这些东西立即变为黄色,然后打对勾   3 选择横纵坐标尺寸原点(其实就是为 ...

  3. C++简单实现对象引用计数示例(转)

    C++简单实现对象引用计数示例 #include <iostream> #include <stdio.h> using namespace std; class String ...

  4. Java单例的实现

    1.声明实例变量(静态) 2.私有化构造函数 3.创建获取实例的方法 public class Singleton{ //创建实例变量 private static Singleton singlet ...

  5. javascript Array method总结

    0.创建 Javascript创建数组的基本方式有两种.第一种是使用Array构造函数. var colors = new Array(); var colors = new Array(20); v ...

  6. 混合minxins

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

  7. 解决:Android4.3锁屏界面Emergency calls only - China Unicom与EMERGENCY CALL语义反复

    从图片中我们能够看到,这里在语义上有一定的反复,当然这是谷歌的原始设计.这个问题在博客上进行共享从表面上来看着实没有什么太大的意义,只是因为Android4.3在锁屏功能上比起老版本号做了非常大的修改 ...

  8. (转)C系程序员面试必知必会之大端小端

      C程序员经常被问及的一道面试题是:什么是大端/小端,怎么样判断是大端/小端?大端小端问题对于嵌入式程序员绝对不会陌生(否则,别告诉我你是搞嵌入式的),它与CPU体系结构有关.比如常见的X86处理器 ...

  9. 翻译:A Tutorial on the Device Tree (Zynq) -- Part III

    A Tutorial on the Device Tree (Zynq) -- Part III 定义外设 可能你读本文是为了给你的设备写一个Linux驱动,在这方面要推荐著名的<Linux D ...

  10. Unity3D游戏开发之粒子系统实现具体解释

     今天为大家分享的是Unity3D中的粒子系统.粒子系统通经常使用来表现烟雾.云等高级效果.是一个十分注重制作技巧的部分.今天我们将以一个气泡的演示实例来一起学习怎样在Unity3D中使用粒子系统 ...