E 1-Trees and Queries(思维+LCA+奇偶性)

题意翻译

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;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/108655302