D. Tree Requests

本文介绍了一种基于二叉树遍历的算法实现,利用递归的方式完成节点的访问,并通过位运算处理特定字符串问题。该算法适用于解决涉及树形结构及字符串操作的相关竞赛题目。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://codeforces.com/gym/241159/problem/D

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
string ch;
vector<int> vec[500100];
vector<int> ans[500100];
vector<pair<ll,ll> > num[500100];
struct node{
	int l;
	int r;
	int depth;
}tree[500100];
int sign;
void dfs(int id,int depth){
	tree[id].l=sign;
	tree[id].depth=depth;
	ans[depth].push_back(id);
	for(int i=0;i<vec[id].size();i++){
		sign+=1;
		dfs(vec[id][i],depth+1);
	}
	tree[id].r=sign+1;
}
int getnum(ll fir,ll sec){
	int co=0;
	for(int i=0;i<13;i++){
		if(fir&(1<<i))
			co++;
		if(sec&(1<<i))
			co++;
	}
	return co;
}
int main(){
	int n,m,temp;
	cin>>n>>m;
	for(int i=2;i<=n;i++){
		scanf("%d",&temp);
		vec[temp].push_back(i);
	}
	cin>>ch;
	sign=0;
	dfs(1,1);
	for(int i=1;i<=n;i++){
		for(int j=0;j<ans[i].size();j++){
			ll fir=0,sec=0;
			if(ch[ans[i][j]-1]>'m')
				fir+=(1<<(ch[ans[i][j]-1]-'n'));
			else
				sec+=(1<<(ch[ans[i][j]-1]-'a'));
			if(j!=0){
				fir^=num[i][j-1].first;
				sec^=num[i][j-1].second;
			}
			num[i].push_back(make_pair<long,long>(fir,sec));
		}
	}
	int v,h;
	while(m--){
		scanf("%d%d",&v,&h);
		int l=0;
		int r=ans[h].size()-1;
		int templ=r+1,tempr=-1;
		while(l<=r){
			int mid=(l+r)/2;
			if(tree[ans[h][mid]].l<=tree[v].l){
				l=mid+1;
			}
			else{
				r=mid-1;
				templ=mid;
			}
		}
		l=0;
		r=ans[h].size()-1;
		while(l<=r){
			int mid=(l+r)/2;
			if(tree[ans[h][mid]].l>=tree[v].r){
				r=mid-1;
			}
			else{
				l=mid+1;
				tempr=mid;
			}
		}
		ll fir=0,sec=0;
		if(templ>0&&tempr<ans[h].size()&&templ<=tempr){
			fir=num[h][tempr].first^num[h][templ-1].first;
			sec=num[h][tempr].second^num[h][templ-1].second;
		}
		else if(templ<=tempr&&templ==0){
			fir=num[h][tempr].first;
			sec=num[h][tempr].second;
		}
		int co=getnum(fir,sec);
		if(co<=1)
			printf("Yes\n");
		else
			printf("No\n");
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值