首页 > 学院 > 开发设计 > 正文

codeforces 570 D. Tree Requests (dsu on the tree)

2019-11-06 06:38:42
字体:
来源:转载
供稿:网友

D. Tree Requeststime limit per test2 secondsmemory limit per test256 megabytesinputstandard inputoutputstandard output

Roman planted a tree consisting of n vertices. Each vertex contains a lowercase English letter. Vertex 1 is the root of the tree, each of the n - 1 remaining vertices has a parent in the tree. Vertex is connected with its parent by an edge. The parent of vertex i is vertex pi, the parent index is always less than the index of the vertex (i.e., pi < i).

The depth of the vertex is the number of nodes on the path from the root to v along the edges. In particular, the depth of the root is equal to 1.

We say that vertex u is in the subtree of vertex v, if we can get from u to v, moving from the vertex to the parent. In particular, vertex v is in its subtree.

Roma gives you m queries, the i-th of which consists of two numbers vihi. Let's consider the vertices in the subtree vi located at depthhi. Determine whether you can use the letters written at these vertices to make a string that is a palindrome. The letters that are written in the vertexes, can be rearranged in any order to make a palindrome, but all letters should be used.

Input

The first line contains two integers nm (1 ≤ n, m ≤ 500 000) — the number of nodes in the tree and queries, respectively.

The following line contains n - 1 integers p2, p3, ..., pn — the parents of vertices from the second to the n-th (1 ≤ pi < i).

The next line contains n lowercase English letters, the i-th of these letters is written on vertex i.

Next m lines describe the queries, the i-th line contains two numbers vihi (1 ≤ vi, hi ≤ n) — the vertex and the depth that appear in thei-th query.

Output

PRint m lines. In the i-th line print "Yes" (without the quotes), if in the i-th query you can make a palindrome from the letters written on the vertices, otherwise print "No" (without the quotes).

Examplesinput
6 51 1 1 3 3zacccd1 13 34 16 11 2output
YesNoYesYesYesNote

String s is a palindrome if reads the same from left to right and from right to left. In particular, an empty string is a palindrome.

Clarification for the sample test.

In the first query there exists only a vertex 1 satisfying all the conditions, we can form a palindrome "z".

In the second query vertices 5 and 6 satisfy condititions, they contain letters "с" and "d" respectively. It is impossible to form a palindrome of them.

In the third query there exist no vertices at depth 1 and in subtree of 4. We may form an empty palindrome.

In the fourth query there exist no vertices in subtree of 6 at depth 1. We may form an empty palindrome.

In the fifth query there vertices 2, 3 and 4 satisfying all conditions above, they contain letters "a", "c" and "c". We may form a palindrome "cac".

题目大意:判断v的子树中所有深度为h的点能否组成一个回文串,每个点上有一个小写字符。

题解:dsu on the tree

将字符压成二进制位,记录每个深度的点的异或值。判断异或值是不是0或者2^x。

#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>#include<cstring>#define N 1000003using namespace std;int tot,n,m,cnt,q[N],nxt[N],point[N],v[N],val[N],son[N];int deep[N],size[N],mp[N],c[N],mark[N],ans[N],num[N];int head[N],u[N],next[N],id[N];char s[N];void add(int x,int y){	tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;	tot++; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;}void build(int x,int y,int i){	tot++; next[tot]=head[x]; head[x]=tot; u[tot]=y; id[tot]=i;}void solve(int x,int fa){	deep[x]=deep[fa]+1; size[x]=1;	for (int i=point[x];i;i=nxt[i]){		if (v[i]==fa) continue;		solve(v[i],x);		size[x]+=size[v[i]];		if(size[son[x]]<size[v[i]]) son[x]=v[i];	}}void change(int x,int fa,int vl){	mp[deep[x]]^=val[x]; num[deep[x]]+=vl;	for (int i=point[x];i;i=nxt[i])	 if (!mark[v[i]]&&v[i]!=fa) change(v[i],x,vl);}void dfs(int x,int fa,bool k){	for (int i=point[x];i;i=nxt[i])	 if (v[i]!=fa&&v[i]!=son[x]) dfs(v[i],x,0);	if (son[x]) dfs(son[x],x,1),mark[son[x]]=1;	change(x,fa,1);	for (int i=head[x];i;i=next[i])    {		int t=mp[u[i]];		if (t==0) ans[id[i]]=1;		for (int j=0;j<26;j++) 		 if (!(t^(1<<j))) ans[id[i]]=1;	}	if(son[x]) mark[son[x]]=0;	if (!k) change(x,fa,-1);}int main(){	freopen("a.in","r",stdin);//	freopen("my.out","w",stdout);	scanf("%d%d",&n,&m);	for (int i=2;i<=n;i++) {		int x; scanf("%d",&x);		add(i,x);	}	scanf("%s",s+1);	for (int i=1;i<=n;i++) val[i]=(1<<(s[i]-'a'));	memset(c,-1,sizeof(c)); tot=0;	for (int i=1;i<=m;i++) {		int x,y; scanf("%d%d",&x,&y);		build(x,y,i);	}	solve(1,0);	dfs(1,0,0);	for (int i=1;i<=m;i++) 	 if (ans[i]) printf("Yes/n");	 else printf("No/n");}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表