[CF Round #294 div2] E. A and B and Lecture Rooms 【树上倍增】
题目链接:E. A and B and Lecture Rooms
题目大意
给定一颗节点数10^5的树,有10^5个询问,每次询问树上到xi, yi这两个点距离相等的点有多少个。
题目分析
若 x==y 直接返回 n。
先求出 x, y 两个点的中点。
先求出 LCA(x, y) = z,假设 Depth[x] >= Depth[y] ,若Depth[x] == Depth[y] ,那么 z 就是它们的中点。
答案就是,n - Size[fx] - Size[fy],fx 是从x向上跳,一直跳到 z 的一个孩子就停止,这个孩子就是 fx。
否则中点一定在从 x -- z -- y 的路径上 x -- z 的一段,为 Jump(x, t) ,t 是 x -- z -- y 长度的一半。如果 x -- z -- y 的长度是奇数,就返回 0。
这个 Jump(a, b) 就是用倍增来求的。
答案就是, Size[o] - Size[fx]。这里的o是中点,fx是从x向上跳,跳到o的一个孩子就停止。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath> using namespace std; const int MaxN = 100000 + 5, MaxLog = 19 + 5; int n, m;
int Depth[MaxN], Father[MaxN], Jump[MaxN][MaxLog], Size[MaxN]; struct Edge
{
int v;
Edge *Next;
} E[MaxN * 2], *P = E, *Point[MaxN]; inline void AddEdge(int x, int y)
{
++P; P -> v = y;
P -> Next = Point[x]; Point[x] = P;
} void DFS(int x, int Dep, int Fa)
{
Depth[x] = Dep;
Father[x] = Fa;
Size[x] = 1;
for (Edge *j = Point[x]; j; j = j -> Next)
{
if (j -> v == Father[x]) continue;
DFS(j -> v, Dep + 1, x);
Size[x] += Size[j -> v];
}
} void Prepare()
{
for (int i = 1; i <= n; ++i) Jump[i][0] = Father[i];
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= 18; ++j)
Jump[i][j] = Jump[Jump[i][j - 1]][j - 1];
} int JumpUp(int x, int y)
{
int ret = x;
for (int i = 0; i <= 18; ++i)
if (y & (1 << i)) ret = Jump[ret][i];
return ret;
} int LCA(int x, int y)
{
if (Depth[x] < Depth[y]) swap(x, y);
int Dif;
Dif = Depth[x] - Depth[y];
if (Dif) x = JumpUp(x, Dif);
if (x == y) return x;
for (int i = 18; i >= 0; --i)
{
if (Jump[x][i] != Jump[y][i])
{
x = Jump[x][i];
y = Jump[y][i];
}
}
return Father[x];
} int Query(int x, int y)
{
if (x == y) return n;
if (Depth[x] < Depth[y]) swap(x, y);
int z, tx, ty, fx, fy, t, o;
z = LCA(x, y);
tx = Depth[x] - Depth[z];
ty = Depth[y] - Depth[z];
t = tx + ty;
if (t & 1) return 0;
if (Depth[x] == Depth[y])
{
fx = JumpUp(x, tx - 1);
fy = JumpUp(y, ty - 1);
return n - Size[fx] - Size[fy];
}
else
{
t >>= 1;
o = JumpUp(x, t);
fx = JumpUp(x, t - 1);
return Size[o] - Size[fx];
}
} int main()
{
scanf("%d", &n);
int a, b;
for (int i = 1; i <= n - 1; ++i)
{
scanf("%d%d", &a, &b);
AddEdge(a, b);
AddEdge(b, a);
}
scanf("%d", &m);
DFS(1, 0, 0);
Prepare();
for (int i = 1; i <= m; ++i)
{
scanf("%d%d", &a, &b);
printf("%d\n", Query(a, b));
}
return 0;
}
[CF Round #294 div2] E. A and B and Lecture Rooms 【树上倍增】的更多相关文章
- [CF Round #294 div2] D. A and B and Interesting Substrings 【Map】
题目链接:D. A and B and Interesting Substrings 题目大意 给定26个小写字母的权值,一共26个整数(有正有负). 给定一个小写字母组成的字符串(长度10^5),求 ...
- Codeforces Round #294 (Div. 2) A and B and Lecture Rooms(LCA 倍增)
A and B and Lecture Rooms time limit per test 2 seconds memory limit per test 256 megabytes input st ...
- CF Round #580(div2)题解报告
CF Round #580(div2)题解报告 T1 T2 水题,不管 T3 构造题,证明大约感性理解一下 我们想既然存在解 \(|a[n + i] - a[i]| = 1\) 这是必须要满足的 既然 ...
- CF round #622 (div2)
CF Round 622 div2 A.简单模拟 B.数学 题意: 某人A参加一个比赛,共n人参加,有两轮,给定这两轮的名次x,y,总排名记为两轮排名和x+y,此值越小名次越前,并且对于与A同分者而言 ...
- [CF Round #295 div2] C. DNA Alignment 【观察与思考0.0】
题目链接:C. DNA Alignment 题目大意就不写了,因为叙述会比较麻烦..还是直接看英文题面吧. 题目分析 经过观察与思考,可以发现,构造的串 T 的每一个字符都与给定串 S 的每一个字符匹 ...
- A. Grasshopper And the String(CF ROUND 378 DIV2)
A. Grasshopper And the String time limit per test 1 second memory limit per test 256 megabytes input ...
- A. Alyona and Numbers(CF ROUND 358 DIV2)
A. Alyona and Numbers time limit per test 1 second memory limit per test 256 megabytes input standar ...
- CF Round#436 div2
额,这次的题目其实挺智障的.所以通过这次比赛,我也发现了自己是一个智障.... 不说太多,说多是泪... A. Fair Game 题意:给你一个数组,看你能否把它均分为两个所有元素均相同的子数组. ...
- CF Round #569 Div2(contest1180)
比赛链接:http://codeforces.com/contest/1180 Problem A 题意:给出n,问方块数.看图理解... Solution: 找一找规律就可以了,发现方块数为2n*( ...
随机推荐
- 对MYSQL IFNULL函数的使用进行了具体的叙述
下文对MYSQL IFNULL函数的使用进行了具体的叙述.供您參考学习.假设您在MYSQL IFNULL函数使用方面遇到过类似的问题,最好还是一看. MYSQL IFNULL(expr1,expr2) ...
- TimeUnit(转)
java.util.concurrent并发库是JDK1.5新增的,其作者是Doug Lea ,此人是个BOSS级别的天才人物了.有了他提供的类库,使得我们对多线程并发.锁有了很大的帮助,减少了并发难 ...
- go 初使用
hello.go package main import "fmt" func main(){ fmt.Println("hello world") 直接运行 ...
- LINUX系统全部参数 sysctl -a + 网络参数设置
http://blog.lifeibo.com/?p=380 1.sysctl sysctl命令被用于在内核运行时动态地修改内核的运行参数,可用的内核参数在目录/proc/sys中 [root@ser ...
- Linux下搭建Oracle11g RAC(3)----创建用户及配置相关文件
配置11gR2 RAC需要安装Oracle Grid Infrastructure软件.Oracle数据库软件,其中Grid软件等同于Oracle 10g的Clusterware集群件.Oracle建 ...
- hibernate自动建表采用UTF-8字符编码
hibernate自动建表采用UTF-8字符编码 hibernate建表默认为UTF-8编码 >>>>>>>>>>>>>& ...
- Object传入String类型和其他
是可以传入的. package com.sun.test; public class Test03 { /** * @param args */ public static void main(Str ...
- SQL_server 的基本操作
1.---------------数据库基本操作 主键 : 1.不重复 2.不为NULL外键 1.取消重复行(消除完全一样的行,保留一行)select distinct cloumname1,clou ...
- [压缩解压缩] SharpZip--压缩、解压缩帮助类
里面有三个类都是用于压缩和解压缩的.大家看下图片 看下面代码吧 /// <summary> /// 类说明:SharpZip /// 编 码 人:苏飞 /// 联系方式:361983679 ...
- 读取Excel异常定义了过多字段的解决方法
/// <summary> /// 从Excel文件导入数据 /// </summary> /// <param name="ExcelStr"> ...