题意翻译
Description
给定一个 n 个点的树,相邻点的距离为 1 。
q 个询问,每个询问包含无个整数: x,y,a,b,kx,y,a,b,k。
含义是:在原树上新连上一条边 (x,y)(x,y) ,要求判断一下从 aa 点是否有距离为 kk 的到 bb 的路径。
注意:
-
每个询问是独立的,即上次询问加上的边,不能为这一次的询问所用。
-
这一条路径也许会重复经过某一条边或某一点。
Input
第 11 行: nn ;
第 2 \cdots n2⋯n 行: 每行 22 个整数 u,vu,v 表示原树上有一条连接结点 u,vu,v 的边。
第 n+1n+1 行:qq ;
接下来 qq 行:每行五个整数: x,y,a,b,kx,y,a,b,k ,意义见上。
Output
共 qq 行。
对于每个询问,判断该路径的存在性。若存在,输出 YES
,反之输出 NO
。
Limits
-
3\le n\le 10^53≤n≤105
-
1\le q\le 10^51≤q≤105
-
u,v,a,b,x,yu,v,a,b,x,y 均在 [1,n][1,n] 范围内。且 u\ne v,x\ne yu=v,x=y。
-
k\in [1,10^9]k∈[1,109]
输入输出样例
输入 #1复制
5 1 2 2 3 3 4 4 5 5 1 3 1 2 2 1 4 1 3 2 1 4 1 3 3 4 2 3 3 9 5 2 3 3 9
输出 #1复制
YES YES NO YES NO
说明/提示
The image below describes the tree (circles and solid lines) and the added edges for each query (dotted lines).
Possible paths for the queries with "YES" answers are:
- 11 -st query: 11 – 33 – 22
- 22 -nd query: 11 – 22 – 33
- 44 -th query: 33 – 44 – 22 – 33 – 44 – 22 – 33 – 44 – 22 – 33
比较容易发现:x到y的距离如果<k,那么不会到。如果>k,那么考虑走出去一条和回来一条(合起来必是偶数),那么就是说如果(k-dis(x,y))%2==0必然能到。这就原来没有加边的情况。
那么就是多了a-b的边的情况。其实就是多了x-a-b-y或者x-b-a-y的情况。
只要求出dis(x,a,b,y)==dis(x,a)+1+dis(b,y),dis(x,b,a,y)==dis(x,b)+dis(a,y)+1以及原来的dis(a,b)是否满足《=k&&差为偶数的情况就好了。
求树上两个点之间的距离---LCA的应用。(这道题还让我发现我原来的lca板子有问题)
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int N=2e5+1000;
typedef long long LL;
LL dep[N],fa[N][22];//fa[i][k]表示节点i的上2^k层的祖先是哪个点
LL lg[N];
//lg[i]的定义:log(i)+1
LL tot,n;
vector<LL>vec[N];
void add(LL x,LL y) {
vec[x].push_back(y);
}
void dfs(LL u,LL last) {//last是u的爸爸!
dep[u]=dep[last]+1;
fa[u][0]=last;
for(int i=1; (1<<i)<=dep[u]; i++)fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=0; i<vec[u].size(); i++)if(vec[u][i]!=last)dfs(vec[u][i],u);
//遍历所有儿砸
}
LL lca(LL x,LL y) {
if(dep[x]<dep[y])swap(x,y);//令x深于y
while(dep[x]!=dep[y])x=fa[x][lg[dep[x]-dep[y]]-1];
if(x==y)return x;
for(int k=lg[dep[x]]; k>=0; k--)
if(fa[x][k]!=fa[y][k])x=fa[x][k],y=fa[y][k];
return fa[x][0];//返回`x的爸爸(lca)
}
LL getdis(LL A,LL B)
{
return dep[A]+dep[B]-2*dep[lca(A,B)];
}
bool check(LL d,LL k)
{
if(d<=k&&d%2==k%2) return true;
return false;
}
int main(void)
{
cin.tie(0);std::ios::sync_with_stdio(false);
cin>>n;
for(int i=1; i<=n; i++) {
lg[i]=lg[i-1];
if(i==1<<lg[i-1])lg[i]++;
}
for(LL i=1;i<n;i++){
LL x,y;cin>>x>>y;
add(x,y);add(y,x);
}
dfs(1,0);
LL m;cin>>m;
while(m--){
LL x,y,a,b,k;cin>>x>>y>>a>>b>>k;
LL ab=getdis(a,b);LL ax=getdis(a,x);LL ay=getdis(a,y);LL bx=getdis(b,x);LL by=getdis(b,y);
if(check(ab,k)||check(ax+1+by,k)||check(ay+1+bx,k)) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}