Loading

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\)的路径

注意路径可以重复走点

\[3\leq n \leq10^5\\ 1\leq q\leq 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");
	}
}
posted @ 2020-11-05 22:01  MQFLLY  阅读(116)  评论(0编辑  收藏  举报