码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #316 (Div. 2) D Tree Requests

时间:2015-08-16 12:27:11      阅读:210      评论:0      收藏:0      [点我收藏+]

标签:codeforces

题目链接

题意:

给定n个点的树,m个询问

1是root,下面给出2——n每个点的父节点,

每个点有一个字母

下面n个小写字母给出每个点的字母。

下面m行给出询问:

询问形如 (u, deep) 问u点的子树中,距离根的深度为deep的所有点的字母能否在任意排列后组成回文串,能输出Yes.不能输出No

根到根的deep = 1,以此类推。

思路:

dfs序,给点重新标号,dfs进入u点的时间戳记为l[u], 离开的时间戳记为r[u], 这样对于某个点u,他的子树节点对应区间都在区间 [l[u], r[u]]内。

把距离根深度相同的点都存到vector里 D[i] 表示深度为i的所有点,在dfs时可以顺便求出。

把询问按深度排序,query[i]表示所有深度为i的询问。

接下来按照深度一层层处理。

对于第i层,把所有处于第i层的节点都更新到26个树状数组上。

然后处理询问,直接查询树状数组上有多少种字母是奇数个的,显然奇数个字母的种数要<=1

处理完第i层,就把树状数组逆向操作,相当于清空树状数组

注意的一个地方就是 询问的深度是任意的,也就是说可能超过实际树的深度,也可能比当前点的深度小。所以需要初始化一下答案。

代码如下:

#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int, int>pii;
const int N = 5e5+10;
int n, m;
int l[N], r[N], top;
char s[N]; 
vector<int> G[N], D[N];
vector<pii> Q[N];
bool ans[N];

struct node
{
	int maxn, c[N];
	void init(int n)
	{
		maxn = n; memset(c, 0, sizeof(c));
	}
	inline int Lowbit(int x){return x&(-x);} 
	void change(int u, int x)
	{
		while(u <= maxn)
		{
			c[u] += x;
			u += Lowbit(u);
		}
	}
	int sum(int x)
	{
		int ans = 0;
		for(int i = x; i >= 1; i -= Lowbit(i))
		{
			ans += c[i];
		}
		return ans;
	}
	int query(int l, int r)
	{
		return sum(r) ^ sum(l-1);
	}		
}t[26];

void dfs(int u, int fa, int dep)
{
	D[dep].push_back(u);
	l[u] = ++top;
	for(vector<int>::iterator i = G[u].begin(); i != G[u].end(); i++)
	{
		if(*i != fa)
		{
			dfs(*i, u, dep+1);
		}
	}
	r[u] = top;
}

int main()
{
	scanf("%d%d", &n, &m);
	fill(ans, ans + m + 10, 1);
	for (int i = 0; i < 26; i++) t[i].init(n);
	for(int i = 2, u; i <= n; i++)
	{
		scanf("%d", &u);
		G[u].push_back(i);
	}
	top = 0;
	dfs(1, 1, 1);
	scanf("%s", s+1);
	for(int i = 1, u, v; i <= m; i++)
	{
		scanf("%d%d", &u, &v);
		Q[v].push_back(pii(u, i));
	}
	for(int i = 1; i <= n; i++)
	{
		if(D[i].size() == 0) break;
		for(vector<int>::iterator j = D[i].begin(); j != D[i].end(); j++)
		{
			t[s[*j] - 'a'].change(l[*j], 1);
		}
		for(int v = 0; v < Q[i].size(); v++)
		{
			pii p = Q[i][v];
			int cnt = 0;
			for(int k = 0; k < 26; k ++)
			{
				if(t[k].query(l[p.first], r[p.first]))
					cnt += t[k].query(l[p.first], r[p.first]) & 1;
			}
			ans[p.second] = cnt <= 1;
		}
		for(vector<int>::iterator iter = D[i].begin(); iter != D[i].end(); iter++)
		{
			t[s[*iter] - 'a'].change(l[*iter], -1);
		}
	}
	for(int i = 1; i <= m; i++)
	{
		ans[i] ? puts("Yes") : puts("No");
	}
	return 0;
}





版权声明:本文为博主原创文章,未经博主允许不得转载。

Codeforces Round #316 (Div. 2) D Tree Requests

标签:codeforces

原文地址:http://blog.csdn.net/doris1104/article/details/47700565

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!