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

Codeforces 570D - Tree Requests【树形转线性,前缀和】

2015-08-26 15:16 225 查看
http://codeforces.com/contest/570/problem/D

给一棵有根树(50w个点)(指定根是1号节点),每个点上有一个小写字母,然后有最多50w个询问,每个询问给出x和f,表示询问以x为根的子树,在第f层的所有节点上的字符能否组成一个回文串

首先树形转线性,把每个点按照DFS序重新标号,然后开个vector记下第i层都有哪些节点,

对于这一层的节点,维护一个前缀和,即某个字母出现过多少次,

这样对于某个询问x,f,我们能知道x为根的子树在线性数组中的序号范围,

然后二分查找第f层位于这个范围的点,通过前缀和就很容易求出来某个字母出现过多少次

因为回文串中最多有一个字母出现奇数次,所以就可以判断是否是回文串。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<queue>
#include<string>
#include<sstream>
#define eps 1e-9
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define MAXN 500005
#define MAXM 40005
#define INF 0x3fffffff
#define PB push_back
#define MP make_pair
#define X first
#define Y second
#define clr(x,y) memset(x,y,sizeof(x));
using namespace std;
typedef long long LL;
int i,j,k,n,m,x,y,T,ans,big,cas,num,len;
bool flag;

vector<int> G[MAXN],D[MAXN];
int op[MAXN],ed[MAXN],lin[MAXN],d[MAXN],mxdp;
int ti[MAXN][26];
char s[MAXN];
int p[30];

void dfs(int u,int f)
{
d[u]=f;
mxdp=max(mxdp,f);
lin[num]=u;//线性数组
op[u]=num;//子树的起始位置
D[f].PB(num); //D[f]表示f层都有哪些节点
num++;
for (int i=0;i<G[u].size();i++)
{
int v=G[u][i];
dfs(v,f+1);
}
ed[u]=num-1;//子树的终止位置
}

int main()
{
scanf("%d%d",&n,&m);
for (i=2;i<=n;i++)
{
scanf("%d",&x);
G[x].PB(i);
}
scanf("%s",s+1);
for (i=1;i<=n;i++) D[i].PB(0);
num=1;
dfs(1,1);
for (i=1;i<=mxdp;i++)
{
for (j=1;j<D[i].size();j++)
{
int u=D[i][j-1];
int v=D[i][j];
for (k=0;k<26;k++) ti[v][k]=ti[u][k];//ti[u][k]表示节点u所在的那一层,从开始到节点u,各个字母出现的次数

ti[v][s[ lin[v]  ]-'a']++;
}
}

for (i=1;i<=m;i++)
{
int u,f;
scanf("%d%d",&u,&f);
int l=op[u],r=ed[u];
int s=upper_bound(D[f].begin(),D[f].end(),l)-D[f].begin()-1;
int e=upper_bound(D[f].begin(),D[f].end(),r)-D[f].begin()-1;
if (s>=e)
{
printf("Yes\n");
}else
{
int cnt=0;
e=D[f][e];
s=D[f][s];
for (k=0;k<26;k++)
if ((ti[e][k]-ti[s][k]) %2 ) cnt++;
if (cnt>1) printf("No\n");
else printf("Yes\n");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: