题目链接: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 【树上倍增】的更多相关文章

  1. [CF Round #294 div2] D. A and B and Interesting Substrings 【Map】

    题目链接:D. A and B and Interesting Substrings 题目大意 给定26个小写字母的权值,一共26个整数(有正有负). 给定一个小写字母组成的字符串(长度10^5),求 ...

  2. 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 ...

  3. CF Round #580(div2)题解报告

    CF Round #580(div2)题解报告 T1 T2 水题,不管 T3 构造题,证明大约感性理解一下 我们想既然存在解 \(|a[n + i] - a[i]| = 1\) 这是必须要满足的 既然 ...

  4. CF round #622 (div2)

    CF Round 622 div2 A.简单模拟 B.数学 题意: 某人A参加一个比赛,共n人参加,有两轮,给定这两轮的名次x,y,总排名记为两轮排名和x+y,此值越小名次越前,并且对于与A同分者而言 ...

  5. [CF Round #295 div2] C. DNA Alignment 【观察与思考0.0】

    题目链接:C. DNA Alignment 题目大意就不写了,因为叙述会比较麻烦..还是直接看英文题面吧. 题目分析 经过观察与思考,可以发现,构造的串 T 的每一个字符都与给定串 S 的每一个字符匹 ...

  6. 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 ...

  7. 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 ...

  8. CF Round#436 div2

    额,这次的题目其实挺智障的.所以通过这次比赛,我也发现了自己是一个智障.... 不说太多,说多是泪... A. Fair Game 题意:给你一个数组,看你能否把它均分为两个所有元素均相同的子数组. ...

  9. CF Round #569 Div2(contest1180)

    比赛链接:http://codeforces.com/contest/1180 Problem A 题意:给出n,问方块数.看图理解... Solution: 找一找规律就可以了,发现方块数为2n*( ...

随机推荐

  1. 节点类(CCNode)

    节点与渲染树 回顾前面的介绍,我们已经知道了精灵.层和场景如何构成一个游戏的框架.精灵属于层,层属于场景,玩家与精灵互动,并导致游戏画面在不同场景中切换.把每个环节拼接在一起,我们得到了一个完整的关系 ...

  2. myeclipse 编码问题

    在使用eclipse+MyEclipse开发中,许多文件编码默认是ISO-8859-1,不支持中文(如常用的JSP),这样我们每次建文件都要手动改编码,其实我们可以在设置文件默认编码,今后再创建时就不 ...

  3. hdu2015java

    偶数求和 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submissio ...

  4. 上传jar包到nexus私服

    摘要 通过网页和maven两种方式,上传本地的jar到nexus私服,以及引用jar时,自动引用依赖 1通过网页上传 这种方法只是上传了jar包.通过maven引用当前jar,不能取得jar的依赖   ...

  5. HDU 4196 Remoteland

    题意:给定一个n,然后让你从1-n中选出某些数乘起来,使得乘积最大,并且乘积必须是完全平方数. 思路:将1-n种每个数都分解素因子,把他们的素因子的幂加起来,如果是偶数,就说明可以构成完全平方数,乘起 ...

  6. Html+Css+Js_之table每隔3行显示不同的两种颜色

    <html> <head> <script type="text/javascript"> /** 最近因项目的需求,有这样的一个问题: 一个t ...

  7. 一个js 变量作用域问题

    一个js 域问题,有一本书 叫 javasrcip pattert 好像是,写的很好,, <!DOCTYPE html> <html> <head lang=" ...

  8. MyXLS案例

    using System; using System.Data; using org.in2bits.MyXls; namespace Maticsoft.Common { /// <summa ...

  9. Js 命名空间注册方法

    MyApp = { namespace: function () { var a = arguments, o = null, i, j, d, rt; for (i = 0; i < a.le ...

  10. 如何在 Debian / Ubuntu 服务器上架设 L2TP / IPSec VPN

    本站的 Rio 最近在一台 Ubuntu 和一台 Debian 主机上配置了 L2TP / IPSec VPN,并在自己的博客上做了记录.原文以英文写就,我把它大致翻译了一下,结合我和 Rio 在设置 ...