[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*( ...
随机推荐
- 史上比较用心的纯代码实现 AutoLayout
入职有两三个月了吧,都是使用 Objective-C 纯代码(虽然有时候偷偷参杂一些 Swift 开源库)来编写公司APP,写布局的时候几乎都是要么在初始化的时候用 initWithFrame,要么就 ...
- UVA - 10239 The Book-shelver's Problem
Description Problem D The Book-shelver's Problem Input: standard input Output: standard output Time ...
- Java基础知识强化之集合框架笔记48:产生10个1~20之间的随机数(要求:随机数不能重复) 简洁版
1. 编写一个程序,获取10个1至20的随机数,要求随机数不能重复. 分析: A: 创建随机数对象 B: 创建一个HashSet集合 C: 判断集合的长度是不是小于10 是:就创建一个随机 ...
- yii2 验证码的使用
@see http://www.yiiframework.com/doc-2.0/yii-captcha-captcha.html 以下根据 MVC 模型的顺序来添加代码 1. model 层, 或 ...
- build/core/config.mk
# 如果定义了ANDROID_BUILD_SHELL,则ANDROID_BUILD_SHELL # 否则使用默认的/bin/bash ifdef ANDROID_BUILD_SHELL SHELL : ...
- C#开发的进化史
1.数据类型的进化 C#1中实现Product类型代码 public class Product { string name; public string Name { get { return na ...
- php 表单的活用
一般表单都是用过POST 方式对数据进行隐秘的传输用, 可以偶尔你也会发现这样的用法,表单不止能够进行隐秘的传输.还能够进行URL的传输,并且是同时进行的 提交页面,在action 后面加了URL后缀 ...
- ActionLink 的一些小问题
近日为群友解答问题时遇到一个问题 由于自己以前确实没碰到过 特此记录一下 起因是群友想要用htmlhelper实现这样一个效果 <a href="我是链接" class=&q ...
- [IO] C# FileOperateHelper文件操作类与源码下载
主要功能如下所示 源码预览 /// <summary> /// 类说明:Assistant /// 编 码 人:苏飞 /// 联系方式:361983679 /// 更新网站:[url]ht ...
- easyui实现datagrid数字排序问题
我们在使用easyui对列进行自动排序的时候(即顺序倒序),正常情况下是通过设置field中的sortable:true属性来控制是否可以排序.但是我们会发现一个有趣的问题,在对数字进行排序的时候,这 ...