Codeforces 519E A and B and Lecture Rooms LCA

题目链接:点击打开链接

题意:

给定n个点的树。

下面n-1行给出树

Q个询问。

每次询问 (u,v)问树上有多少个点到u点距离=到v点距离

思路:

首先这两个点的距离必须是偶数,若为奇数答案就是0

然后用lca找到中间节点即可。

trick : u==v ans = n

#include"cstdio"
#include"iostream"
#include"queue"
#include"algorithm"
#include"set"
#include"queue"
#include"cmath"
#include"string.h"
#include"vector"
using namespace std;
template <class T>
inline bool rd(T &ret) {
    char c; int sgn;
    if (c = getchar(), c == EOF) return 0;
    while (c != '-' && (c<'0' || c>'9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return 1;
}
template <class T>
inline void pt(T x) {
    if (x <0) {
        putchar('-');
        x = -x;
    }
    if (x>9) pt(x / 10);
    putchar(x % 10 + '0');
}
#define N 100500
struct Edge{
    int from, to, nex;
}edge[2 * N];
int head[N], edgenum, fa[N][20], dep[N], siz[N];  //fa[i][x] 是i的第2^x个父亲(如果超过范围就是根)
void add(int u, int v){
    Edge E = { u, v, head[u] };
    edge[edgenum] = E;
    head[u] = edgenum++;
}
void bfs(int root){
    queue<int> q;
    fa[root][0] = root; dep[root] = 0; siz[root] = 0;
    q.push(root);
    while (!q.empty()){
        int u = q.front(); q.pop();
        for (int i = 1; i<20; i++)fa[u][i] = fa[fa[u][i - 1]][i - 1];
        for (int i = head[u]; ~i; i = edge[i].nex){
            int v = edge[i].to; if (v == fa[u][0])continue;
            dep[v] = dep[u] + 1; fa[v][0] = u;
            q.push(v);
        }
    }
}
void dfs(int u, int f){
    siz[u] = 1;
    for (int i = head[u]; ~i; i = edge[i].nex){
        int v = edge[i].to; if (v == f)continue;
        dfs(v, u);
        siz[u] += siz[v];
    }
}
int Lca(int x, int y){
    if (dep[x]<dep[y])swap(x, y);
    for (int i = 0; i<20; i++)if ((dep[x] - dep[y])&(1 << i))x = fa[x][i];
    if (x == y)return x;
    for (int i = 19; i >= 0; i--)if (fa[x][i] != fa[y][i])x = fa[x][i], y = fa[y][i];
    return fa[x][0];
}
void init(){ memset(head, -1, sizeof head); edgenum = 0; }

int n, m;
int go(int D, int x){
    while (D){
        int z = log10(1.0*D) / log10(2.0);
        x = fa[x][z];
        D -= 1 << z;
    }
    return x;
}
int main(){
    rd(n);
    init();
    for (int i = 1, u, v; i < n; i++){
        rd(u); rd(v);
        add(u, v); add(v, u);
    }
    bfs(1);
    dfs(1, 1);
    rd(m);
    int x, y;
    while (m--){
        rd(x); rd(y);
        if (x == y){ pt(n); putchar('\n'); continue; }
        if (dep[x]>dep[y])swap(x, y);
        int l = Lca(x, y);
        int len = dep[x] - dep[l] + dep[y] - dep[l];
        if (len & 1){
            putchar('0');
        }
        else {
            len = len / 2 - 1;
            int a = go(len, y), b = fa[a][0];
            if (b == l){
                pt(n - siz[a] - siz[go(len, x)]);
            }
            else pt(siz[b] - siz[a]);
        }
        putchar('\n');
    }
    return 0;
}
时间: 2024-10-06 12:34:42

Codeforces 519E A and B and Lecture Rooms LCA的相关文章

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

Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 519E Description A and B are preparing themselves for programming contests. The University where A and B study is a set of rooms connected

Codefources 519E. A and B and Lecture Rooms LCA

简单LCA: 求树上距离给定两个点a,b距离相等的点有多少个 先预处理出每个节点的孩子个数sum[x],求出a,b的LCA,根据深度就可以知道两个点的距离,距离为偶数的有解.... 根据lca在a,b之间的位置不同分情况讨论: 设a与lca距离为 ha , b与lca距离为 hb 1:lca在a,b正中间既a,b分别属于lca的两个子树中, 结果为: n-sum[ a往上距离lca ha-1 的点] - sum[ b往上距离lca hb-1 的点] 2:a,b两个点相对lca一上一下. c:a,

[Codeforces#519E] A and B and Lecture Rooms

Codeforces题号:#519E 出处: Codeforces 主要算法:最近公共祖先LCA(倍增法) 难度:4.5 思路分析: 题意:询问给出一棵无根树上任意两点a,b,求关于所有点i,\(dist(a,i) = dist(b,i)\)的点的数量.要求每一次询问在O(log n)的时间复杂度内完成. 由于在树上求距离,并且还要O(log n),自然会联想到LCA.由于边权是1,那么点到根的距离就是该点的深度.这个深度可以在dfs预处理的过程中处理完成.那么两个点之间的距离就是两个点到根节点

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 set of rooms connected by corridors. Overall, the University has n rooms connected by n - 1corridors so that you can get from any room to any other one

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

题意: 给你一棵有n个节点的树,给你m次询问,查询给两个点,问树上有多少个点到这两个点的距离是相等的.树上所有边的边权是1. 思路: 很容易想到通过记录dep和找到lca来找到两个点之间的距离,然后分情况讨论. 一开始困扰我的问题是如果lca不是正中间的点,如何在比较低的复杂度的层面上求解中点. 倍增法lca不光可以在logn的时间复杂度内查询某两个点的lca,还可以实现在logm的时间复杂度能查询某个节点的第m个父亲节点. 算法的核心是用二进制的运算来实现查询. #include<bits/s

A and B and Lecture Rooms(LCA)

题目描述 A and B are preparing themselves for programming contests. The University where A and B study is a set of rooms connected by corridors. Overall, the University has n rooms connected by n?-?1 corridors so that you can get from any room to any oth

CodeForces 519E 树形DP A and B and Lecture Rooms

给出一棵树,有若干次询问,每次询问距两个点u, v距离相等的点的个数. 情况还挺多的,少侠不妨去看官方题解.^_^ 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 using namespace std; 7 8 const int maxn = 100000 + 10; 9 10

Codeforces Round #294 Div2 E(A and B and Lecture Rooms)

Problem 给一棵树,含有N个节点,N?1条边.进行M次查询,每次给定两个节点x,y,问树上有多少个节点到x,y的距离相同. Limits TimeLimit(ms):2000 MemoryLimit(MB):256 N,M∈[1,105] x,y∈[1,N] Look up Original Problem From here Solution 求出a,b两个节点的lca,再找到lca?>a或lca?>b上的某个节点v使得dis(v,a)=dis(v,b).分v=lca,v∈lca?&g

Codeforces Round #287 D.The Maths Lecture

The Maths Lecture 题意:求存在后缀Si mod k =0,的n位数的数目.(n <=1000,k<=100); 用f[i][j]代表 长为i位,模k等于j的数的个数. 可以用 f[i+1][(t*10i+j)%k]=∑f[i][j]+(j==0),(t*10i+j)%k!=0;动态规划 这样可以求出所有f[n][i] i>0 的值. 最后用9*10^(n-1)-∑f[n][i] 就可以得到 答案 #include <bits/stdc++.h> using