这道题用 LCA 就可以水过去 , 但是我太弱了 QAQ 倍增写LCA总是写残...于是就写了树链剖分...

其实也不难写 , 线段树也不用用到 , 自己YY一下然后搞一搞就过了...速度还挺快的好像= = #9

----------------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
 
#define rep( i , n ) for( int i = 0 ; i < n ; i++ )
#define clr( x , c ) memset( x , c , sizeof( x ) )
#define REP( x ) for( edge* e = head[ x ] ; e ; e = e -> next )
 
using namespace std;
 
const int maxn = 500000 + 5;
 
struct edge {
int to;
edge* next;
};
 
edge* pt , EDGE[ maxn << 1 ];
edge* head[ maxn ];
 
void edge_init() {
pt = EDGE;
clr( head , 0 );
}
 
void add( int u , int v ) {
pt -> to = v;
pt -> next = head[ u ];
head[ u ] = pt++;
}
#define add_edge( u , v ) add( u , v ) , add( v , u )
 
 
int fa[ maxn ] , top[ maxn ] , size[ maxn ] , son[ maxn ] , dep[ maxn ];
int id[ maxn ] , _id[ maxn ] , id_cnt = 0 , TOP;
 
void dfs( int x ) {
size[ x ] = 1;
son[ x ] = -1;
REP( x ) {
int to = e -> to;
if( to == fa[ x ] ) continue;
dep[ to ] = dep[ x ] + 1;
fa[ to ] = x;
dfs( to );
size[ x ] += size[ to ];
if( son[ x ] == - 1 || size[ to ] > size[ son[ x ] ] )
   son[ x ] = to;
}
}
 
void DFS( int x ) {
top[ x ] = TOP;
id[ x ] = ++id_cnt;
_id[ id_cnt ] = x;
if( son[ x ] != -1 )
   DFS( son[ x ] );
REP( x ) if( id[ e -> to ] < 0 )
   DFS( TOP = e -> to );
}
 
void DFS_init() {
clr( id , -1 );
dfs( dep[ 0 ] = 0 );
DFS( TOP = 0 );
}
 
int Q_LCA( int x , int y ) {
while( top[ x ] != top[ y ] ) {
if( dep[ top[ x ] ] < dep[ top[ y ] ] ) 
   swap( x , y );
x = fa[ top[ x ] ];
}
return dep[ x ] < dep[ y ] ? x : y;
}
 
int Q_dist( int x , int y ) {
int res = 0;
while( top[ x ] != top[ y ] ) {
if( dep[ top[ x ] ] < dep[ top[ y ] ] )
   swap( x , y );
res += id[ x ] - id[ top[ x ] ];
x = fa[ top[ x ] ];
res++;
}
if( dep[ x ] < dep[ y ] )
   swap( x , y );
return res + id[ x ] - id[ y ];
}
 
 
int ans[ 2 ];
void work( int x , int y , int z ) {
int LCA[ 3 ] = { Q_LCA( x , y ) , Q_LCA( x , z ) , Q_LCA( y , z ) };
if( LCA[ 0 ] == LCA[ 1 ] )
   ans[ 0 ] = LCA[ 2 ];
else if( LCA[ 0 ] == LCA[ 2 ] )
   ans[ 0 ] = LCA[ 1 ];
else 
   ans[ 0 ] = LCA[ 0 ];
ans[ 1 ] = Q_dist( x , ans[ 0 ] ) + Q_dist( y , ans[ 0 ] ) + Q_dist( z , ans[ 0 ] );
}
 
inline int read() {
int res = 0;
char c = getchar();
while( ! isdigit( c ) ) c = getchar();
while( isdigit( c ) ) {
res = res * 10 + c - '0';
c = getchar();
}
return res;
}
 
int main() {
freopen( "test.in" , "r" , stdin );
int n = read() , m = read();
edge_init();
rep( i , n - 1 ) {
int u = read() , v = read();
u-- , v--;
add_edge( u , v );
}
DFS_init();
while( m-- ) {
int x = read() , y = read() , z = read();
x-- , y-- , z--;
work( x , y , z );
printf( "%d %d\n" , ans[ 0 ] + 1 , ans[ 1 ] );
}
return 0;
}

----------------------------------------------------------------------------------

1787: [Ahoi2008]Meet 紧急集合

Time Limit: 20 Sec  Memory Limit: 162 MB
Submit: 1542  Solved: 683
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

6 4
1 2
2 3
2 4
4 5
5 6
4 5 6
6 3 1
2 4 4
6 6 6

Sample Output

5 2
2 5
4 1
6 0

HINT

Source

BZOJ 1787: [Ahoi2008]Meet 紧急集合( 树链剖分 )的更多相关文章

  1. bzoj 1787: [Ahoi2008]Meet 紧急集合

    1787: [Ahoi2008]Meet 紧急集合 Description Input Output Sample Input 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 3 1 ...

  2. bzoj 1787 [Ahoi2008]Meet 紧急集合(1832 [AHOI2008]聚会)

    1787: [Ahoi2008]Meet 紧急集合 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 1841  Solved: 857[Submit][ ...

  3. BZOJ 1787: [Ahoi2008]Meet 紧急集合 LCA

    1787: [Ahoi2008]Meet 紧急集合 Description Input Output Sample Input 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 3 1 ...

  4. BZOJ 1787: [Ahoi2008]Meet 紧急集合(lca+贪心)

    [Ahoi2008]Meet 紧急集合 Description Input Output Sample Input 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 3 1 2 4 4 ...

  5. bzoj 1787: [Ahoi2008]Meet 紧急集合【树链剖分lca】

    对于三个点求最小路径长度和,答案肯定在某两个点的lca上,因为如果把集合点定在公共lca上,一定有两个点汇合后再一起上到lca,这样显然不如让剩下的那个点下来 这个lca可能是深度最深的--但是我懒得 ...

  6. BZOJ——1787: [Ahoi2008]Meet 紧急集合

    http://www.lydsy.com/JudgeOnline/problem.php?id=1787 题目描述 输入 输出 样例输入 6 4 1 2 2 3 2 4 4 5 5 6 4 5 6 6 ...

  7. 1787: [Ahoi2008]Meet 紧急集合

    1787: [Ahoi2008]Meet 紧急集合 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 1482  Solved: 652[Submit][ ...

  8. BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)

    前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...

  9. [bzoj 3531][SDOI2014]旅行(树链剖分+动态开点线段树)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3531 分析: 对于每个颜色(颜色<=10^5)都建立一颗线段树 什么!那么不是M ...

随机推荐

  1. Hibernate的搭建及使用

    1.创建普通的java项目. 因为Hibernate是一个轻量级的框架,不像servlet,还必须需要tomcat的支持,Hibernate只要jdk支持即可. 2.引入jar包. 可以在项目中直接引 ...

  2. javascript函数querySelector

    querySelector用于获得dom节点,可以接受三种类型的参数:id(#),class(.),标签.很像jquery的选择器.不过只能返回一个子孙元素,但是jquery选择器的话,可以返回一组元 ...

  3. Android UiAutomator 自动化测试环境搭建---新手1

    1.首先需要准备的工具有 1.java jdk 2. android开发工具 adt 3.ant 安装包(如果下载adt里面有) 2.首先安装java环境,jdk这个百度就可以了. 3.android ...

  4. jQuery 自学笔记—3

    jQuery 语法实例 $(this).hide() 演示 jQuery hide() 函数,隐藏当前的 HTML 元素. $("#test").hide() 演示 jQuery ...

  5. 基于Visual C++2013拆解世界五百强面试题--题10-找出N个数种最大的K个数

    有一亿个整数,请找出最大的 1000 个,要求时间越短越好, 空间占用越好越好. 如果不考虑时间效率,很容易想到解决方法,我们只需存储前一千个数, 然后依次读入后面的数和这一千个数组比较,替换其中比较 ...

  6. Scrambled Polygon(斜率排序)

    Scrambled Polygon Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 7799   Accepted: 3707 ...

  7. GDB调试之暂停

    暂停机制: 有3种方式可以通知GDB暂停程序的执行. a.断点: 通知GDB在程序中的特定位置暂停执行: b.监视点:通知GDB当特定内存位置(或者涉及一个或多个位置的表达式)的值发生变化时暂停执行: ...

  8. ASP.NET页面传值的几种方式

    页面传值是学习asp.net初期都会面临的一个问题,总的来说有页面传值. 存储对象传值.ajax.类.model.表单等!下面欧柏泰克和大家一起来看看asp.net页面传值方式一般有哪些?常用的较简单 ...

  9. jz2440不能成功地启动文件系统, Failed to execute /linuxrc.

    文件系统加载失败,错误信息提示:    VFS: Mounted root (nfs filesystem).    Freeing init memory: 140K    Failed to ex ...

  10. STL之vector(向量)

    C++编程语言中有一种叫做Vector的应用方法,它的作用在实际编程中是非常重要的,这里详细介绍一下C++ Vector的相关应用技巧及基本内容: Construct vector #include ...