您的位置:首页 > 产品设计 > UI/UE

Codeforces Round #316 (Div. 2)-D. Tree Requests-DFS+二分+hash

2015-08-15 16:32 561 查看
dfs求出每个点的深度,并用in、out数组记录该点 管辖的节点范围(in[x]和out[x]之间的数都是x节点所管辖的内容)

从而实现 以深度 为主要因素,以 字母类型为次要因素 把所有节点的内容分类记录在cal[depth][27]数组里 (hash思想)

对于每次查询 ,x,h 先判断 depth[x]是否大于等于h 若大于,则yes

若小于,则 在cal[h]的【1-27】里遍历,寻找是否有 in[x]--out[x]之间的点,有则二分得到个数,判断奇偶,因为要形成回文串,只要奇数个数不超过一就可以了

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
const int maxn = 500005;

 
 int tm[maxn];
 char vv[maxn];
vector <int> q[maxn];
int depth[maxn];
int  in[maxn];
int out[maxn];
int knum=0; 
vector <int> cal[maxn][27];
 

int dfs1(int x,int cur)
{
	int i;
	cal[cur][vv[x]-'a'+1].push_back(++knum);
	in[x]=knum;
	for (i=0;i<q[x].size();i++)
	{ 
		depth[q[x][i]]=cur+1;
			dfs1(q[x][i],cur+1);
	} 
	out[x]=knum;
return 0;
} 
int main()
{
	

	int n,m,i,k,t1,t2;
	scanf("%d%d",&n,&m);
	
	for (i=2;i<=n;i++)
	{
		scanf("%d",&tm[i]);
		q[tm[i]].push_back(i);
	}
	if (n==1) getchar();
	getchar(); tm[1]=1;
	scanf("%c",&vv[1]);
	for (i=2;i<=n;i++)
	{
		scanf("%c",&vv[i]);
	}
	depth[1]=1; 
	dfs1(1,1); //prepared for [depth,charactor];

 
	for (k=1;k<=m;k++)
	{
		scanf("%d%d",&t1,&t2);
		if (depth[t1]>=t2)
		printf("Yes\n");
		else
		{
		 
		 
			int line=0,flag=0;
			for (i=1;i<=26;i++)
			{
	 
			 int tf1=lower_bound(cal[t2][i].begin(),cal[t2][i].end(),in[t1])- cal[t2][i].begin()+1;
			 int tf2=upper_bound(cal[t2][i].begin(),cal[t2][i].end(),out[t1])- cal[t2][i].begin()+1;
			 if ((tf2-tf1)%2)
			 {
				 if (line==0)
				 {line=1;continue;}
				 if (line==1)
				 {flag=1;break;}
			 }
				

			}
			if (flag==0)
			printf("Yes\n");
			else
			{printf("No\n");}
		}

	}
	return 0;
	
	
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: