CodeForces-1304 E 1-Trees and Queries 树上思维 CodeForces-1304 E 1-Trees and Queries 树上思维
题意
给定一颗(n)个点的树,树上相邻点的距离为1.
现有(q)个询问,每个询问包含5个整数(x,y,a,b,k)
在原树上连上一条新的边((x,y))判断是否存在(a)到(b)的长度为(k)的路径
注意路径可以重复走点
[3leq n leq10^5\
1leq qleq 10^5\
k leq 10^9
]
分析
先不考虑这题的特殊性,
注意到可以重复走,仅当两点间的简单路径长度小于等于(k)且和(k)的差是偶数的时候才输出YES
偶数是因为既然要重复走,多走的那部分贡献肯定是偶数
那么想想新连一条边带来的影响
好像没什么影响?使得从简单路径多拓展到了可以通过这条路径走
所以相当于两条简单路径的叠加
因此就是把原来的一条多了两条而已
代码
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
ull readull(){
ull x = 0;
int f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return f * x;
}
int readint(){
int x = 0;
int f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = x * 10 + ch - '0';
ch = getchar();
}
return f * x;
}
const int maxn = 1e5 + 5;
int fa[maxn],son[maxn],dep[maxn],siz[maxn];
int top[maxn],pre[maxn],id[maxn];
int tt;
vector<int> e[maxn];
void dfs1(int u){
siz[u] = 1;
for(auto v:e[u]){
if(v == fa[u]) continue;
dep[v] = dep[u] + 1;
fa[v] = u;
dfs1(v);
siz[u] += siz[v];
if(siz[v] > siz[son[u]])
son[u] = v;
}
}
void dfs2(int u,int x){
pre[u] = ++tt;
id[tt] = u;
top[u] = x;
if(!son[u]) return;
dfs2(son[u],x);
for(auto v:e[u]){
if(v == fa[u] || v == son[u]) continue;
dfs2(v,v);
}
}
int lca(int x,int y){
while(top[x] != top[y]){
if(dep[top[x]] > dep[top[y]])
x = fa[top[x]];
else
y = fa[top[y]];
}
return dep[x] > dep[y] ? y : x;
}
int dis(int a,int b){
return dep[a] + dep[b] - 2 * dep[lca(a,b)];
}
bool check(int a,int b){
return a <= b && (b - a) % 2 == 0;
}
int main(){
int n = readint();
for(int i = 1;i < n;i++){
int u = readint();
int v = readint();
e[u].push_back(v);
e[v].push_back(u);
}
dfs1(1);
dfs2(1,1);
int q = readint();
while(q--){
int x = readint();
int y = readint();
int a = readint();
int b = readint();
int ab = dis(a,b);
int xa = dis(x,a);
int xb = dis(x,b);
int ay = dis(a,y);
int by = dis(b,y);
int k = readint();
if(check(ab,k) || check(xa + by + 1,k) || check(xb + ay + 1,k)) puts("YES");
else puts("NO");
}
}