[Codeforces1304E]1-Trees and Queries

哇比赛的时候查不出来wtcl。。

还有,我不相信是 E 题

题意 Description

给定一个 \(n\) 个点的树,相邻点的距离为 \(1\)

\(q\) 个询问,每个询问包含5个整数: \(x,y,a,b,k\)

含义是:在原树上新连上一条边 \((x,y)\) ,要求判断一下从 \(a\) 点是否有距离为 \(k\) 的到 \(b\) 的路径。

注意:

  • 每个询问是独立的,即上次询问加上的边,不能为这一次的询问所用。

  • 这一条路径也许会重复经过某一条边或某一点。

题解 Solution

涉及树上距离,考虑 LCA 。

对于每个询问,我们先判断一下 \(a,b\) 间有没有长度为 \(k\) 的路径,再判断一下经过边 \(x,y\) 的路径有没有长度为 \(k\) 的即可。

对于第一个:

下面的 \(\operatorname{dist}(u,v)\) 表示 \(u,v\) 的最短距离。

  • 快速求得 \(\operatorname{dist}(u,v)\) 可以通过 LCA 来求,公式: \(\operatorname{dist}(u,v)=depth_u+depth_v-2\times depth_{\operatorname{LCA}(u,v)}\) 。其中 \(\operatorname{LCA}(u,v)\) 表示结点 \(u,v\) 的 最近公共祖先。

  • 先求出 \(a,b\) 的最短距离 \(D = \operatorname{dist}(a,b)\)。假如说 \(D\)\(k\) 的奇偶性一致且 \(k\ge D\) 的话,那么就是 YES 。为什么是奇偶性?因为如果把这条最短的路径“折一下”(1->2->3->4 折成 1->2->3->2->3->4),总长度会加二,奇偶性不变。倘若 \(k\ge D\) ,那么这样一直折下去,路径长度一定可以到达 \(k\)

  • 对于新加入的边,我们计算出 \(D'=\min (\operatorname{dist}(a,x)+\operatorname{dist}(b,y)+1,\operatorname{dist}(a,y)+\operatorname{dist}(b,x)+1)\),即 \(a\)\(b\) 经过边 \((x,y)\) 的最短路径的长度。如果 \(D'\)\(k\) 的奇偶性一致且 \(k \ge D'\) 的话就是可行的。

  • 注意, \(D\)\(D'\) 必须 \(\le k\) 否则是不成立的。因为“折”是不可以“折”负数次的。

代码 Source Code

#include
#include
#include
#include
using namespace std;

int get_int()
{
    int x=0,f=1;char c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
        x=x*10+c-'0',c=getchar();
    return f*x;
}

const int N=1e5+5;
vector G[N];
int depth[N],father[N];
int maxson[N],size[N],top[N]/*link tops*/;
int n,s,m;

void DFS1(const int &now,const int &from)
{
    father[now]=from,depth[now]=depth[from]+1,size[now]=1;
    for(register int i=0;i1)DFS2(maxson[now],lktp);
    for(register int i=0;i=depth[top[v]])?u=father[top[u]]:v=father[top[v]];
    return depth[u]
  • P.S. LCA部分是用树链剖分写的,倍增或 RMQ 也可以。

算法复杂度 \(\Theta (n+q\log n)\)

你可能感兴趣的:([Codeforces1304E]1-Trees and Queries)