BZOJ5479: tree
Description
给出一棵树,根节点为1
给出两个集合,集合由树上节点组成
从两个集合分别选出一个元素,求其LCA
问LCA的最大深度是多少
Input
第一行给出数据组数T
对于每组数据
第一行给出N,M,代表树的节点个数及询问次数
接下来N-1行,每行两个正整数u,v,表示u,v之间有边
接下来2M行,每两个表示一个询问
询问的第一行,第一行正整数a代表集合A中元素个数
接下来a个正整数,表示集合中的节点
询问的第二行,第一行正整数b代表集合B中元素个数
接下来b个正整数,表示集合中的节点
T<=5,N,M<=100000
sigma(a)+sigma(b)<=200000
a,b<=N
Output
对于每个询问,一行一个整数表示结果
Sample Input
1
7 3
1 2
1 3
3 4
3 5
4 6
4 7
1 6
1 7
2 6 7
1 7
2 5 4
2 3 2
Sample Output
3
4
2
Solution
考虑怎么样才会让lca的深度最大,两个点的必须尽可能相近。
那么有一个直观的贪心想法,处理出整个树的dfs序(最好树剖,因为这样会优先编号重儿子),将b数组按dfs序排序,每次对于a中的元素,在b中二分与它dfs序最接近的两个点,对lca的深度取max。
多组数据,记得清空数组。
#include <bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define il inline
namespace io {
#define in(a) a=read()
#define out(a) write(a)
#define outn(a) out(a),putchar('\n')
#define I_int int
inline I_int read() {
I_int x = 0 , f = 1 ; char c = getchar() ;
while( c < '0' || c > '9' ) { if( c == '-' ) f = -1 ; c = getchar() ; }
while( c >= '0' && c <= '9' ) { x = x * 10 + c - '0' ; c = getchar() ; }
return x * f ;
}
char F[ 200 ] ;
inline void write( I_int x ) {
if( x == 0 ) { putchar( '0' ) ; return ; }
I_int tmp = x > 0 ? x : -x ;
if( x < 0 ) putchar( '-' ) ;
int cnt = 0 ;
while( tmp > 0 ) {
F[ cnt ++ ] = tmp % 10 + '0' ;
tmp /= 10 ;
}
while( cnt > 0 ) putchar( F[ -- cnt ] ) ;
}
#undef I_int
}
using namespace io ;
using namespace std ;
#define N 200010
int T;
int n, m, head[N], cnt;
struct edge {
int to, nxt;
} e[N<<1];
int fa[N], dep[N], siz[N], top[N], id[N];
int x, y;
struct Node {
int dfn, val;
}a[N], b[N];
void dfs1(int u) {
siz[u] = 1;
for(int i = head[u]; i; i = e[i].nxt) {
if(e[i].to == fa[u]) continue;
fa[e[i].to] = u;
dep[e[i].to] = dep[u] + 1;
dfs1(e[i].to);
siz[u] += siz[e[i].to];
}
}
int tim = 0;
void dfs2(int u, int topf) {
id[u] = ++tim;
top[u] = topf;
int k = 0;
for(int i = head[u]; i; i = e[i].nxt) {
if(e[i].to == fa[u]) continue;
if(siz[e[i].to] > siz[k]) k = e[i].to;
}
if(!k) return;
dfs2(k, topf);
for(int i = head[u]; i; i = e[i].nxt) {
if(e[i].to == fa[u] || e[i].to == k) continue;
dfs2(e[i].to, e[i].to);
}
}
int lca(int x, int y) {
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x, y);
return x;
}
void init() {
cnt = 0; tim = 0;
memset(head, 0, sizeof(head));
memset(dep, 0, sizeof(dep));
memset(id, 0, sizeof(id));
memset(top, 0, sizeof(top));
memset(siz, 0, sizeof(siz));
memset(fa, 0, sizeof(fa));
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
}
void ins(int u, int v) {
e[++cnt].to = v;
e[cnt].nxt = head[u];
head[u] = cnt;
}
int find(int t) {
int l = 1, r = y, ans = y;
while(l <= r) {
int mid = (l + r) >> 1;
if(b[mid].dfn >= t) ans = mid, r = mid - 1;
else l = mid + 1;
}
return ans;
}
bool operator < (Node a, Node b) {
return a.dfn < b.dfn;
}
int main() {
T = read();
while(T--) {
n = read(), m = read();
init();
for(int i = 1; i < n; ++i) {
int u = read(), v = read();
ins(u, v); ins(v, u);
}
dep[1] = 1;
dfs1(1); dfs2(1, 1);
while(m--) {
int ans = 0;
x = read();
for(int i = 1; i <= x; ++i) a[i].val = read(), a[i].dfn = id[a[i].val];
y = read();
for(int i = 1; i <= y; ++i) b[i].val = read(), b[i].dfn = id[b[i].val];
sort(b + 1, b + y + 1);
for(int i = 1; i <= x; ++i) {
int t = find(a[i].dfn);
ans = max(ans, dep[lca(b[t].val, a[i].val)]);
ans = max(ans, dep[lca(b[t - 1].val, a[i].val)]);
}
outn(ans);
}
}
}
BZOJ5479: tree的更多相关文章
- [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法
二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...
- SAP CRM 树视图(TREE VIEW)
树视图可以用于表示数据的层次. 例如:SAP CRM中的组织结构数据可以表示为树视图. 在SAP CRM Web UI的术语当中,没有像表视图(table view)或者表单视图(form view) ...
- 无限分级和tree结构数据增删改【提供Demo下载】
无限分级 很多时候我们不确定等级关系的层级,这个时候就需要用到无限分级了. 说到无限分级,又要扯到递归调用了.(据说频繁递归是很耗性能的),在此我们需要先设计好表机构,用来存储无限分级的数据.当然,以 ...
- 2000条你应知的WPF小姿势 基础篇<45-50 Visual Tree&Logic Tree 附带两个小工具>
在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000Things You Should Know About C# 和 2,0 ...
- Leetcode 笔记 110 - Balanced Binary Tree
题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...
- Leetcode 笔记 100 - Same Tree
题目链接:Same Tree | LeetCode OJ Given two binary trees, write a function to check if they are equal or ...
- Leetcode 笔记 99 - Recover Binary Search Tree
题目链接:Recover Binary Search Tree | LeetCode OJ Two elements of a binary search tree (BST) are swapped ...
- Leetcode 笔记 98 - Validate Binary Search Tree
题目链接:Validate Binary Search Tree | LeetCode OJ Given a binary tree, determine if it is a valid binar ...
- Leetcode 笔记 101 - Symmetric Tree
题目链接:Symmetric Tree | LeetCode OJ Given a binary tree, check whether it is a mirror of itself (ie, s ...
随机推荐
- 用Hexo在GitHub上搭建个人博客
我用Hexo在GitHub上搭建好了自己的博客,我的这第一篇博客就来说说搭建的过程. 1 环境配置 本文使用环境如下: Windows 10 node.js v8.1.3 git v2.13.2 np ...
- ReactiveCocoa(III)
flatMap(FlattenStrategy.latest) observe(on: UIScheduler()).startWithResult 切换线程: observeOn(UISchedul ...
- Presto 学习参考资料
Presto 文档资料: 0.1版:Presto 0.100 Documentation 0.213版:Presto 0.213 Documentation 阿里云 presto 学习资料:https ...
- 委托、匿名函数到lambda表达式
在C#2.0之前就有委托了,在2.0之后又引入了匿名方法,C#3.0之后,又引入了Lambda表达式,他们三者之间的顺序是:委托->匿名表达式->Lambda表达式,微软的一步步升级,带给 ...
- jmeter压力测试及抓包
如何使用jmeter进行分布式压力测试? 1.其他的压力机启动jmeter-server 2.在主控机jmeter的配置文件jmeter.properties里面找到,remote_hosts=xx, ...
- ubuntu_virtualenv
sudo pip install virtualenv 1.安装virtualenv(需要先安装pip): $ [sudo] pip install virtualenv 2.创建虚拟环境: $ vi ...
- 离开(切换)当前页面时改变页面title
document.addEventListener('visibilitychange', function () { if (document.visibilityState == 'hidden' ...
- Android几种解析XML方式的比较
https://blog.csdn.net/isee361820238/article/details/52371342 一.使用SAX解析XML SAX(Simple API for XML) 使用 ...
- nodejs安装淘宝npm镜像【cnpm】
安装完nodejs后[自带npm] 如果npm无法使用或需要FQ,可以先安装cnpm,然后使用cnpm install安装模块 安装全局cnpm npm install -g cnpm --regis ...
- mysql INSERT ... ON DUPLICATE KEY UPDATE语句
网上关于INSERT ... ON DUPLICATE KEY UPDATE大多数文章都是同一篇文章转来转去,首先这个语法的目的是为了解决重复性,当数据库中存在某个记录时,执行这条语句会更新它,而不存 ...