P5836 USACO19DEC Milk Visits S

题目描述

Farmer John 计划建造 \(N\) 个农场,用 \(N-1\) 条道路连接,构成一棵树(也就是说,所有农场之间都互相可以到达,并且没有环)。每个农场有一头奶牛,品种为更赛牛或荷斯坦牛之一。

Farmer John 的 \(M\) 个朋友经常前来拜访他。在朋友 \(i\) 拜访之时,Farmer John 会与他的朋友沿着从农场 \(A_i\) 到农场 \(B_i\) 之间的唯一路径行走(可能有 \(A_i = B_i\))。除此之外,他们还可以品尝他们经过的路径上任意一头奶牛的牛奶。由于 Farmer John 的朋友们大多数也是农场主,他们对牛奶有着极强的偏好。他的有些朋友只喝更赛牛的牛奶,其余的只喝荷斯坦牛的牛奶。任何 Farmer John 的朋友只有在他们访问时能喝到他们偏好的牛奶才会高兴。

请求出每个朋友在拜访过后是否会高兴。

输入格式

输入的第一行包含两个整数 \(N\)\(M\)

第二行包含一个长为 \(N\) 的字符串。如果第 \(i\) 个农场中的奶牛是更赛牛,则字符串中第 \(i\) 个字符为 G,如果第 \(i\) 个农场中的奶牛是荷斯坦牛则为 H

以下 \(N-1\) 行,每行包含两个不同的整数 \(X\)\(Y\)\(1 \leq X, Y \leq N\)),表示农场 \(X\)\(Y\) 之间有一条道路。

以下 \(M\) 行,每行包含整数 \(A_i\)\(B_i\),以及一个字符 \(C_i\)\(A_i\)\(B_i\) 表示朋友 \(i\) 拜访时行走的路径的端点,\(C_i\)GH 之一,表示第 \(i\) 个朋友喜欢更赛牛的牛奶或是荷斯坦牛的牛奶。

输出格式

输出一个长为 \(M\) 的二进制字符串。如果第 \(i\) 个朋友会感到高兴,则字符串的第 \(i\) 个字符为 1,否则为 0

样例 #1

样例输入 #1

5 5
HHGHG
1 2
2 3
2 4
1 5
1 4 H
1 4 G
1 3 G
1 3 H
5 5 H

样例输出 #1

10110

提示

在这里,从农场 1 到农场 4 的路径包括农场 1、2 和 4。所有这些农场里都是荷斯坦牛,所以第一个朋友会感到满意,而第二个朋友不会。

关于部分分:

测试点 \(1\) 样例。

测试点 \(2\sim 5\) 满足 \(N\le 10^3\)\(M\le 2\cdot 10^3\)

对于 \(100\%\) 的数据,\(1 \leq N \leq 10^5\)\(1 \leq M \leq 10^5\)

分析

定义 \(f_{x,i,0}\)\(x\) 的第 \(2^i\) 级祖先,\(f_{x,i,1}\) 为在 \(x\)\(x\)\(2^i\) 级祖先的链上是否含有 H\(f_{x,i,2}\) 为在 \(x\)\(x\)\(2^i\) 级祖先的链上是否含有 G

所以先倍增求 \(f\),再像 LCA 那样两个点向上跳,如果遇到相应的奶牛种类就返回 \(1\)并输出,直到结束都没有就返回 \(0\)

#include<bits/stdc++.h>
using namespace std;
int n,m,dep[100005],f[100005][25][5],lg[100005],a[100005];
char c;
vector<int>e[100005];
void dfs(int u,int fa){
	dep[u]=dep[fa]+1,f[u][0][0]=fa;
	f[u][0][1]=(a[u]==1||a[fa]==1),f[u][0][2]=(a[u]==2||a[fa]==2);
	for(int i=1;i<=lg[dep[u]];i++){
		f[u][i][0]=f[f[u][i-1][0]][i-1][0];
		f[u][i][1]=(f[f[u][i-1][0]][i-1][1]==1||f[u][i-1][1]==1);
		f[u][i][2]=(f[f[u][i-1][0]][i-1][2]==1||f[u][i-1][2]==1);
	}
	for(int i=0;i<e[u].size();i++){
		if(e[u][i]^fa)dfs(e[u][i],u);
	}
}
int lca(int x,int y,int w){
	if(dep[x]<dep[y])swap(x,y);
	while(dep[x]>dep[y]){
		if(f[x][lg[dep[x]-dep[y]]][w])return 1;
		x=f[x][lg[dep[x]-dep[y]]][0];
	}
	if(x==y){
		if(a[x]==w)return 1;
		else return 0;
	}
	for(int i=lg[dep[x]];i>=0;i--){
		if(f[x][i][0]^f[y][i][0]){
			if(f[x][i][w]==1||f[y][i][w]==1)return 1;
			x=f[x][i][0],y=f[y][i][0];
		}
	}
	if(f[x][0][w]==1||f[y][0][w]==1)return 1;
	else return 0;
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>c;	
		if(c=='H')a[i]=1;
		else a[i]=2;
	}
	for(int i=1,x,y;i<n;i++){
		cin>>x>>y;
		e[x].push_back(y),e[y].push_back(x);
	}
	for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
	dfs(1,0);
	for(int i=1,x,y;i<=m;i++){
		cin>>x>>y>>c;
		if(c=='H')cout<<lca(x,y,1);
		else cout<<lca(x,y,2);
	}
	return 0;
} 
posted @ 2023-06-23 22:10  alex_liu09  阅读(29)  评论(0)    收藏  举报