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 ...
随机推荐
- 在统一软件开发过程中使用UML
如何在统一软件开发过程中使用UML? 起始阶段常用UML图 在起始阶段,通常有用例图.类图.活动图.顺序图等UML图的参与. 获取用户需求之后首先要将这些需求转化为系统的顶层用例图. 在确定了用例之后 ...
- 多语言(Java、.NET、Node.js)混合架构下开源调用链追踪APM项目初步选型
1. 背景 我们的技术栈包括了Java..NET.Node.js等,并且采用了分布式的技术架构,系统性能管理.问题排查成本越来越高. 2. 基本诉求 针对我们的情况,这里列出了选型的主要条件,作为最终 ...
- word2vector 资料
http://blog.csdn.net/garfielder007/article/details/51345201 https://cs224d.stanford.edu/lecture_note ...
- django之auth认证系统
Django自带的用户认证 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. Djang ...
- 异常检测LOF
局部异常因子算法-Local Outlier Factor(LOF)在数据挖掘方面,经常需要在做特征工程和模型训练之前对数据进行清洗,剔除无效数据和异常数据.异常检测也是数据挖掘的一个方向,用于反作弊 ...
- 【javascript】获取 格式化时间
function getDate() { var myDate = new Date(); var month = myDate.getMonth() + 1; var day = myDate.ge ...
- 调用微信JS-SDK配置签名
前后端进行分开开发: 1:后端实现获取 +++接口凭证:access_token (公众号的全局唯一接口调用凭据) ** GET 获取:https://api.weixin.qq.com/cgi-bi ...
- myeclipse项目导入IDEA
1.import project from external model (不需要删除myeclipse多余文件) https://blog.csdn.net/d276031034/artic ...
- UART接口与COM口的区别
原文地址:https://blog.csdn.net/wordwarwordwar/article/details/78883732 简单的讲:(UART与COM) 嵌入式里面说的串口,一般是指UAR ...
- How to install john deere service advisor 4.2.005 on win 10 64bit
How to install john deere service advisor 4.2.005 with the February 2016 data base disks on a machin ...