题意:
给一颗树,根节点深度为1,每一个节点都代表一个子母。
数据输入:
节点数 询问数
从编号为2的节点开始依次输入其父节点的编号(共有节点数减1个数字输入)
字符串有节点数个小写字母
接下来询问
a b
代表以a为根节点的子树在深度为b(包含)的范围内所有节点的字母能否组成回文串。
能输出Yes,不能输出No
思路:
1.dfs序,对于每个节点,我们在深度和字母组成的二维数组里边记录进入节点和离开节点的时间戳。
2.用到upper_bound和lower_bound函数对该深度之下各个时间的字母数量进行统计。
3.由字母组成回文串的关键是最多有一个字母出现奇数次。
/************************************************************************* > File Name: G.cpp > Author: ttpond > Created Time: 2015-8-16 16:42:27 ************************************************************************/ #include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<math.h> #include<vector> #include<map> #include<queue> #include<stack> using namespace std; const int N=5E5+7; int now=0; vector<int>tree[N]; vector<int>ans[N][27]; int start[N]; int endd[N]; char str[N]; int n,m; void dfs(int deep,int num) { now++; ans[deep][str[num]-‘a‘].push_back(now); start[num]=now; vector<int>::iterator it; for(it=tree[num].begin(); it!=tree[num].end(); it++) { dfs(deep+1,*it); } endd[num]=now; } int main() { scanf("%d%d",&n,&m); //printf("%d %d\n",n,m); int tmp; for(int i=2; i<=n; i++) { scanf("%d",&tmp); tree[tmp].push_back(i); } getchar(); scanf("%s",str+1); //puts(str+1); dfs(1,1); int v,h; int ttt,rel=0; for(int i=0; i<m; i++) { rel=0; scanf("%d%d",&v,&h); //printf("%d %d\n",v,h); for(int i=0; i<26; i++) { ttt=upper_bound(ans[h][i].begin(),ans[h][i].end(),endd[v])-lower_bound(ans[h][i].begin(),ans[h][i].end(),start[v]); //printf("%d\n",ttt); if(ttt&1) { rel+=1; if(rel>1) break; } } if(rel>1) printf("No\n"); else printf("Yes\n"); } }
时间: 2024-10-25 01:48:39