传送门:>Here<

题意:询问给出一棵无根树上任意两点$a,b$,求关于所有点$i$,$dist(a,i) = dist(b,i)$的点的数量。要求每一次询问在$O(log n)$的时间复杂度内完成。

解题思路

由于在树上求距离,并且还要$O(log n)$,自然会联想到$LCA$。由于边权是$1$,那么点到根的距离就是该点的深度。这个深度可以在$dfs$预处理的过程中处理完成。那么两个点之间的距离就是两个点到根节点的距离减去两点的LCA到根节点距离的两倍。这个随便yy一下就好了。

得到$a,b$间的距离$D$以后,分类讨论。(设$a$的深度$\geq \ b$的深度)

(1)若$D$为奇数,则一定不存在任何一个点到$a,b$的距离相等。因此得到$0$.

(2)若$D$为偶数:

(一)$a,b$两点分别在$LCA$的两棵子树上。

①$a,b$两点深度相同。此时很简单,最近的一个距离相等的点就是$a,b$的$LCA$。也很容易想到$LCA$的祖先也全都符合。但真的只有这些吗?$LCA$的祖先的其他儿子好像也满足诶……$LCA$的其他子树(除了$a,b$)好像也满足诶……因此我们得到结论,在这种情况下得到的答案应当是$n - size[LCA的左子树] - size[LCA的右子树]$

②深度不同。那么我们找到中间节点$Mid$,$Mid$里除有$a$的子树外其他子树都符合,并且$Mid$以上的节点都不会符合,因此答案是$size[Mid] - size[有a的那棵子树]$

(二)$a,b$在同一条链上,即$b$就是$LCA$

和①类似,中间深度的节点减去含$a$的子树即可

因此我们要做的不过是在$dfs$的过程中维护好$size$和$dep$。但一直困惑我的是有$a$的那个子树怎么快速得到?答案其实很暴力……再倍增一遍……

Code

太坑了!调试了一个多小时竟然是因为$LCA$的预处理dfs中$(1<<i)$打成了$i$,导致$TLE$得莫名其妙。还是$LCA$板子不熟啊……

/** This Program is written by QiXingZhi **/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#include <cmath>
#define r read()
#define Max(a,b) (((a)>(b)) ? (a) : (b))
#define Min(a,b) (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
const int N = ;
const int INF = ;
inline int read(){
int x = ; int w = ; register int c = getchar();
while(c ^ '-' && (c < '' || c > '')) c = getchar();
if(c == '-') w = -, c = getchar();
while(c >= '' && c <= '') x = (x << ) +(x << ) + c - '', c = getchar();
return x * w;
}
int n,x,y,ans;
int f[N][],dep[N],size[N];
vector <int> G[N];
inline void AddEdge(int u, int v){
G[u].push_back(v);
}
void LcaInit(int x, int father, int _d){
dep[x] = _d;
f[x][] = father;
size[x] = ;
for(int i = ; (<<i) <= _d; ++i){
f[x][i] = f[f[x][i-]][i-];
}
int sz,to;
sz = G[x].size();
for(int i = ; i < sz; ++i){
to = G[x][i];
if(to == father) continue;
LcaInit(to,x,_d+);
size[x] += size[to];
}
}
inline int GetDepNode(int x, int _d){
int tmp = x;
for(int i = ; i >= ; --i){
if(dep[tmp]-(<<i) < _d) continue;
tmp = f[tmp][i];
}
return tmp;
}
inline void LCA(int a, int b){
if(dep[a] < dep[b]){
swap(a,b);
}
int _a = a, _b = b;
for(int i = ; i >= ; --i){
if(dep[a]-(<<i) < dep[b]) continue;
a = f[a][i];
}
int LCA;
if(a == b){
LCA = a;
}
else{
for(int i = ; i >= ; --i){
if(f[a][i] == f[b][i]) continue;
a = f[a][i];
b = f[b][i];
}
LCA = f[a][];
}
int Dist = dep[_a]-dep[LCA]+dep[_b]-dep[LCA];
if(Dist & ){
ans = ;
return;
}
else{
if(_b == LCA){
int dep_Mid = (dep[_a] + dep[_b]) / ;
ans = size[GetDepNode(_a,dep_Mid)] - size[GetDepNode(_a,dep_Mid+)];
}
else{
if(dep[_a] != dep[_b]){
int dep_Mid = dep[_a] - (Dist/);
ans = size[GetDepNode(_a,dep_Mid)] - size[GetDepNode(_a,dep_Mid+)];
}
else{
ans = n - size[GetDepNode(_a,dep[LCA]+)] - size[GetDepNode(_b,dep[LCA]+)];
}
}
}
}
int main(){
n = r;
for(int i = ; i < n; ++i){
x = r, y = r;
AddEdge(x,y);
AddEdge(y,x);
}
LcaInit(,,);
int Q = r;
while(Q--){
x = r, y = r;
ans = ;
if(x != y){
LCA(x,y);
printf("%d\n",ans);
}
else{
printf("%d\n",n);
}
}
return ;
}

Codeforces519 E. A and B and Lecture Rooms的更多相关文章

  1. [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= ...

  2. codeforces 519E A and B and Lecture Rooms(LCA,倍增)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud E. A and B and Lecture Rooms A and B are ...

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

  4. codeforces 519E A and B and Lecture Rooms LCA倍增

    Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Prac ...

  5. CodeForces 519E A and B and Lecture Rooms(倍增)

    A and B are preparing themselves for programming contests. The University where A and B study is a s ...

  6. A and B and Lecture Rooms(LCA)

    题目描述 A and B are preparing themselves for programming contests. The University where A and B study i ...

  7. [codeforces 519E]E. A and B and Lecture Rooms(树上倍增)

    题目:http://codeforces.com/problemset/problem/519/E 题意:给你一个n个点的树,有m个询问(x,y),对于每个询问回答树上有多少个点和x,y点的距离相等 ...

  8. Codeforces 519 E. A and B and Lecture Rooms

    Description 询问一个树上与两点距离相等的点的个数. Sol 倍增求LCA. 一棵树上距离两点相等,要么就只有两点的中点,要么就是与中点相连的所有点. 有些结论很容易证明,如果距离是偶数,那 ...

  9. Codeforces 519E A and B and Lecture Rooms [倍增法LCA]

    题意: 给你一棵有n个节点的树,给你m次询问,查询给两个点,问树上有多少个点到这两个点的距离是相等的.树上所有边的边权是1. 思路: 很容易想到通过记录dep和找到lca来找到两个点之间的距离,然后分 ...

随机推荐

  1. vue及Eelement使用过程中遇到的一些问题

    在做项目的过程中,目前主要遇到了以下几个问题: 一.样式问题 1.样式中使用scoped的问题: 主要表现在从一个页面跳到另一个页面时,第二个页面的样式不能正确显示,通过刷新才能恢复页面的预定样式. ...

  2. 爱奇艺2017秋招笔试(C++智能设备方向)

    虽然有方向,但是好像题目都是随机题库抽取. 选择题都很基础...挖坑,待更新 编程: 一. 奇异数: 如果一个数字满足以下条件,我们就称它为奇异数: 1.   这个数字至少有两位 2. 这个数的最低两 ...

  3. Streaming Principal Component Analysis in Noisy Settings

    论文背景: 面对来袭的数据,连续样本不一定是不相关的,甚至不是同分布的. 当前,大部分在线PCA都只关注准确性,而忽视时效性! 噪声?数据缺失,观测有偏,重大异常? 论文内容: Section 2 O ...

  4. An error occurred while updating the entries. See the inner exception for details.

    EF插入或更新数据时出现错误提示:An error occurred while updating the entries. See the inner exception for details.的 ...

  5. 记一个JS树结构路径查找

    var a=[ { "id" : "0000", "text" : "R1", "children" ...

  6. echarts使用笔记五:echarts的Zoom控件

    option = { title: { text: '趋势' }, tooltip : { trigger: 'axis', show:true, axisPointer : { // 坐标轴指示器, ...

  7. HTTL之初印象

    概述 HTTL (Hyper-Text Template Language) 是一个高性能的开源JAVA模板引擎, 适用于动态HTML页面输出, 可替代JSP页面, 指令和Velocity相似. 简洁 ...

  8. 03 测试Hadoop hdfs 上传 与 mr

    1.随便在哪个目录新增一个文档.内容随便输入 mkdir words 2.在hdfs 中新建文件输入目录 ./hdfs dfs -mkdir /test 3.把新建的文档 (/home/hadoop/ ...

  9. [转帖]Windows平台卸载Oracle的办法

    1.首先打开服务:选中此电脑->点击右键->选择管理->选择服务和应用程序->服务 在右边查看并停止以 oracle开头的服务(选中正在运行的以oracle开头的服务-> ...

  10. flutter屏幕适配

    现在的手机品牌和型号越来越多,导致我们平时写布局的时候会在个不同的移动设备上显示的效果不同, 比如我们的设计稿一个View的大小是300px,如果直接写300px,可能在当前设备显示正常,但到了其他设 ...