题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4822

Problem Description
Three countries, Red, Yellow, and Blue are in war. The map of battlefield is a tree, which means that there are N nodes and (N – 1) edges that connect all the nodes. Each country has a base station located in one node. All three countries will not place their station in the same node. And each country will start from its base station to occupy other nodes. For each node, country A will occupy it iff other two country's base stations have larger distances to that node compared to country A. Note that each edge is of the same length.

Given three country's base station, you task is to calculate the number of nodes each country occupies (the base station is counted).

 
Input
The input starts with a single integer T (1 ≤ T ≤ 10), the number of test cases.
Each test cases starts with a single integer N (3 ≤ N ≤ 10 ^ 5), which means there are N nodes in the tree.
Then N - 1 lines follow, each containing two integers u and v (1 ≤ u, v ≤ N, u ≠ v), which means that there is an edge between node u and node v.
Then a single integer M (1 ≤ M ≤ 10 ^ 5) follows, indicating the number of queries.
Each the next M lines contains a query of three integers a, b, c (1 ≤ a, b, c ≤ N, a, b, c are distinct), which indicates the base stations of the three countries respectively.
 
Output
For each query, you should output three integers in a single line, separated by white spaces, indicating the number of nodes that each country occupies. Note that the order is the same as the country's base station input.
 
题目大意:给一棵n个点的树,每次询问有三个点,问离每个点比另外两个点近的点有多少个。
思路:贴一下官方题解:
——————————————————————————————————————————————————————————————————————————————

本题抽象的题意是给出一棵树,有许多询问,每次询问,给出3个点,问有多少个点,到这三个点的最短距离是递增的。
首先考虑两个点的简单情况,因为是树,有特殊性,任意两点间只有唯一的一条路,找到路的中点,就可以把树分成两部分,其中一部分的点是合法解。
回到本题,问题就变成了两个子树的交集。这个考虑一个子树是否是另一子树的子树即可。用dfs序列来判断即可。
时间复杂度是O(nlogn)

——————————————————————————————————————————————————————————————————————————————
即考虑每一个点,求这个点与另两个点劈开成的两颗子树(或者是整棵树减去一棵子树),这里要用到树上倍增求第k祖先。然后求两个子树的交,这个分类讨论一下即可。
PS:用G++交居然栈溢出了。只好换C++开栈了。
 
 
代码(2781MS):
 #ifdef ONLINE_JUDGE
#pragma comment(linker, "/STACK:1024000000,1024000000")
#endif // ONLINE_JUDGE #include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std; const int MAXV = ;
const int MAXE = ;
const int MAX_LOG = ; int head[MAXV], ecnt;
int to[MAXE], next[MAXE];
int n, m, T; void init() {
memset(head + , -, n * sizeof(int));
ecnt = ;
} void add_edge(int u, int v) {
to[ecnt] = v; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; next[ecnt] = head[v]; head[v] = ecnt++;
} int fa[MAX_LOG][MAXV];
int size[MAXV], dep[MAXV]; void dfs(int u, int f, int depth) {
fa[][u] = f; size[u] = ; dep[u] = depth;
for(int p = head[u]; ~p; p = next[p]) {
int v = to[p];
if(v == f) continue;
dfs(v, u, depth + );
size[u] += size[v];
}
} void initfa() {
dfs(, -, );
for(int k = ; k < MAX_LOG - ; ++k) {
for(int u = ; u <= n; ++u) {
if(fa[k][u] == -) fa[k + ][u] = ;
else fa[k + ][u] = fa[k][fa[k][u]];
}
}
} int upslope(int u, int p) {
for(int k = ; k < MAX_LOG; ++k) {
if((p >> k) & ) u = fa[k][u];
}
return u;
} int lca(int u, int v) {
if(dep[u] < dep[v]) swap(u, v);
u = upslope(u, dep[u] - dep[v]);
if(u == v) return u;
for(int k = MAX_LOG - ; k >= ; --k) {
if(fa[k][u] != fa[k][v])
u = fa[k][u], v = fa[k][v];
}
return fa[][u];
} struct Node {
int type, r;
Node(int type, int r): type(type), r(r) {}
}; Node get_middle(int a, int b, int ab) {
int len = dep[a] + dep[b] - * dep[ab];
if(dep[a] >= dep[b]) {
return Node(, upslope(a, (len - ) / ));
} else {
return Node(, upslope(b, len / ));
}
} int calc(int a, int b, int c, int ab, int ac) {
Node bn = get_middle(a, b, ab), cn = get_middle(a, c, ac);
if(bn.type == && cn.type == ) {
if(dep[bn.r] < dep[cn.r]) swap(bn, cn);
if(lca(bn.r, cn.r) == cn.r) return size[bn.r];
else return ;
} else if(bn.type == && cn.type == ) {
if(dep[bn.r] < dep[cn.r]) swap(bn, cn);
if(lca(bn.r, cn.r) == cn.r) return n - size[cn.r];
else return n - size[bn.r] - size[cn.r];
} else {
if(bn.type == ) swap(bn, cn);
int t = lca(bn.r, cn.r);
if(t == cn.r) return n - size[cn.r];
if(t == bn.r) return size[bn.r] - size[cn.r];
return size[bn.r];
}
} int main() {
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
init();
for(int i = , u, v; i < n; ++i) {
scanf("%d%d", &u, &v);
add_edge(u, v);
}
initfa();
scanf("%d", &m);
for(int i = , a, b, c; i < m; ++i) {
scanf("%d%d%d", &a, &b, &c);
int ab = lca(a, b), ac = lca(a, c), bc = lca(b, c);
printf("%d %d %d\n", calc(a, b, c, ab, ac), calc(b, a, c, ab, bc), calc(c, a, b, ac, bc));
}
}
}

HDU 4822 Tri-war(LCA树上倍增)(2013 Asia Regional Changchun)的更多相关文章

  1. HDU 4816 Bathysphere(数学)(2013 Asia Regional Changchun)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4816 Problem Description The Bathysphere is a spheric ...

  2. 2013 Asia Regional Changchun C

    Little Tiger vs. Deep Monkey Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K ( ...

  3. 2013 Asia Regional Changchun I 题,HDU(4821),Hash

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=4821 解题报告:搞了很久,总算搞出来了,还是参考了一下网上的解法,的确很巧,和上次湘潭的比 ...

  4. 2013 Asia Regional Changchun

    Hard Code http://acm.hdu.edu.cn/showproblem.php?pid=4813 #include<cstdio> ]; int main(){ int t ...

  5. HDU 5444 Elven Postman (2015 ACM/ICPC Asia Regional Changchun Online)

    Elven Postman Elves are very peculiar creatures. As we all know, they can live for a very long time ...

  6. 2015 ACM/ICPC Asia Regional Changchun Online HDU 5444 Elven Postman【二叉排序树的建树和遍历查找】

    Elven Postman Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)T ...

  7. HDU 4291 A Short problem(2012 ACM/ICPC Asia Regional Chengdu Online)

    HDU 4291 A Short problem(2012 ACM/ICPC Asia Regional Chengdu Online) 题目链接http://acm.hdu.edu.cn/showp ...

  8. (并查集)Travel -- hdu -- 5441(2015 ACM/ICPC Asia Regional Changchun Online )

    http://acm.hdu.edu.cn/showproblem.php?pid=5441 Travel Time Limit: 1500/1000 MS (Java/Others)    Memo ...

  9. (二叉树)Elven Postman -- HDU -- 54444(2015 ACM/ICPC Asia Regional Changchun Online)

    http://acm.hdu.edu.cn/showproblem.php?pid=5444 Elven Postman Time Limit: 1500/1000 MS (Java/Others)  ...

随机推荐

  1. MYSQL启动报1067错误,系统日志中是“服务 mysql 意外停止” Mysql日志中则是:“Plugin \'FEDERATED\' is disabled”

    MYSQL启动报1067错误,系统日志中是"服务 mysql 意外停止" Mysql日志中则是:"Plugin \'FEDERATED\' is disabled&quo ...

  2. Bluetooth LMP介绍

    目录 1. 介绍 2. 数据包格式(Packet Format) 3. Procedure Rules 4. 通用回应消息(General Response Messages) 5. 设备特性(Dev ...

  3. 蓝牙HID协议笔记

    1.概述     The Human Interface Device (HID)定义了蓝牙在人机接口设备中的协议.特征和使用规程.典型的应用包括蓝牙鼠标.蓝牙键盘.蓝牙游戏手柄等.该协议改编自USB ...

  4. Archiver 浅析

    归档是一个过程,即用某种格式来保存一个或多个对象,以便以后还原这些对象.通常,这个过程包括将(多个)对象写入文件中,以便以后读取该对象. 两种归档数据的方法:属性列表和带键值的编码. 属性列表局限性很 ...

  5. 读书笔记——《图解TCP/IP》(4/4)

    经典摘抄 第八章 应用层协议概要 1.应用协议是为了实现某种应用而设计和创造的协议. 2.TCP/IP的应用层包含了管理通信连接的会话层功能.转换数据格式的表示层功能,还包括与对端主机交互的应用层功能 ...

  6. C/C++的编译器|编译环境(非常全面的比较)

    C/C++编译器的一些易混淆概念,总结一下. 关于什么是Unix-like操作系统,常见操作系统间差异,什么是操作系统接口等等,请参考<操作系统宝鉴>. C/C++编译器有哪些? 首先是如 ...

  7. How to control printer orientation(Landscape / Portrait) for an AX report in X++

    You should try this: 1. Set property Orientation on your report design to Auto 2. In your fetch meth ...

  8. 【上手centos】二、C/C++的编译与运行

    尝试了一下运行C/C++程序,觉得最好还是记下来吧,毕竟也算是从不知到已知呢么. 我用sublime写了2个程序,test.c和test.cpp,分别是C程序和C++程序 step1:编译: #gcc ...

  9. imx6 framebuffer 分析

    分析imx6 framebuffer设备和驱动的注册过程. Tony Liu, 2016-8-31, Shenzhen 相关文件: arch/arm/mach-mx6/board-mx6q_sabre ...

  10. Using dbms_shared_pool.purge to remove a single task from the library cache

    我们都知道可是使用 alter system flush shared_pool 来清除shared pool 信息,当时不能指定清除某个对象.因为在系统繁忙的时侯 使用 alter system f ...