codeforces #316 D.Tree Requests (巧妙的dfs序)

来源:互联网 发布:中巴经济走廊意义知乎 编辑:程序博客网 时间:2024/06/02 04:14

题目:http://codeforces.com/contest/570/problem/D

题意:给定一棵n个节点的树,每个节点有一个字符。现在有q次查询,每次查询给出两个整数v、h,问节点v的深度为h的孩子节点所表示的字符能否构成回文串。

分析:假如我们对每个节点以dfs序重新编号,那么节点u的所有孩子节点的编号是连续的,并且我们知道开始的位置和末位置。现在要找深度为h的孩子节点,我们只需把孩子节点按深度分类存起来。怎么判断这些孩子节点能否构成回文串?只需判断每种字符的个数的奇偶性,为奇数个的字符不能超过1个。我们再另外按字母分个类,二分统计个数就行了。

代码:

#include <bits/stdc++.h>using namespace std;typedef long long LL;typedef unsigned long long ULL;const LL INF = 1E9+9;const int maxn = 5e5+7;vector <int > son[maxn];vector <int > buf[maxn][26];int in[maxn],out[maxn],num;char str[maxn];void dfs(int deep,int root){buf[deep][str[root]-'a'].push_back(num);in[root]=num++;for(const auto &s:son[root])dfs(deep+1,s);out[root]=num;}int main(){int n,q,x,i,j,h,v;cin>>n>>q;for(i=2;i<=n;i++){scanf("%d",&x);son[x].push_back(i);}scanf("%s",str+1);dfs(1,1);while(q--){scanf("%d%d",&v,&h);int has=0;for(i=0;i<26 && has<2;i++){int cnt=lower_bound(buf[h][i].begin(),buf[h][i].end(),out[v])-lower_bound(buf[h][i].begin(),buf[h][i].end(),in[v]);cnt&1?has++:has;}printf("%s\n",has>1?"No":"Yes");}return 0;}

0 0