CF 570D Tree Requests

Posted kcn999

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF 570D Tree Requests相关的知识,希望对你有一定的参考价值。

题目大意

在一棵以结点 (1) 为根的树上有 (n) 个结点,每个结点上有一个小写字母,每个点的深度定义为根结点到该结点路径上的点数。
现在有 (m) 次询问 (a,b) ,要求输出以结点 (a) 为根的子树上深度为 (b) 的所有结点上的字母,重新排列后能否形成回文串。
其中,(1 leq n leq 5 imes 10^5)(1 leq m leq 5 imes 10^5)
?

题解

显然对于深度相同且在同一子树中的结点,若字母形成回文串,那么最多只有 (1) 种字母的出现次数为奇数。
因为只有 (26) 种字母,且每种字母的出现次数可以用 (0) / (1) 表示,所以我们可以用一个二进制数来表示每种字母出现的状态。

然而观察到如果把每个结点 (v_i) 的每一个深度 (d_i) 的答案都统计下来,要开大小为 (n^2) 的数组,显然会 MLE,而且时间复杂度也很大。
因此,我们可以先把查询记录下来,只记录查询的答案。

剩下的很显然,直接用 dsu on tree 即可。对于每一个深度 (d_i) ,用一个数组 (vis(d_i)) 表示当前深度遍历到子树结点的字母状态。
(vis(d_i) - operatorname{lowbit}left(visleft(d_i ight) ight) = 0) 时,显然答案为 ( exttt{Yes}) ,否则为 ( exttt{No})

#include <cstdio>

#define MAX_N (500000 + 5)
#define MAX_M (500000 + 5)

#define lowbit(x) ((x)&-(x))

struct Node
{
	int dep;
	int size;
	int son;
	int val;
};

struct Edge
{
	int to;
	int next;
};

int n, m;
char str[MAX_N];
Node a[MAX_N];
int h[MAX_N];
Edge e[MAX_N];
int hq[MAX_M];
Edge q[MAX_M];
int vis[MAX_N];
bool ans[MAX_M];

void Add_Edge(int, int, int);
void Add_Query(int, int, int);
void DFS1(int);
void DFS2(int);
void DSU(int, bool);

int main()
{
	scanf("%d%d", &n, &m);
	int u, v;
	for (int i = 2; i <= n; ++i)
	{
		scanf("%d", &u);
		Add_Edge(u, i, i - 1);
	}
	scanf("%s", str + 1);
	for (int i = 1; i <= n; ++i)
	{
		a[i].val = 1 << str[i] - ‘a‘;
	}
	for (int i = 1; i <= m; ++i)
	{
		scanf("%d%d", &u, &v);
		Add_Query(u, v, i);
	}
	a[1].dep = 1;
	DFS1(1);
	DSU(1, 0);
	for (int i = 1; i <= m; ++i)
	{
		printf(ans[i] ? "Yes
" : "No
");
	}
	return 0;
}

void Add_Edge(int u, int v, int idx)
{
	e[idx].to = v;
	e[idx].next = h[u];
	h[u] = idx;
}

void Add_Query(int u, int v, int idx)
{
	q[idx].to = v;
	q[idx].next = hq[u];
	hq[u] = idx;
}

void DFS1(int u)
{
	a[u].size = 1;
	int v;
	for (int i = h[u]; i; i = e[i].next)
	{
		v = e[i].to;
		a[v].dep = a[u].dep + 1; 
		DFS1(v);
		a[u].size += a[v].size;
		if (a[v].size > a[a[u].son].size) a[u].son = v; 
	}
}

void DFS2(int u)
{
	vis[a[u].dep] ^= a[u].val;
	for (int i = h[u]; i; i = e[i].next)
	{
		DFS2(e[i].to);
	}
}

void DSU(int u, bool is)
{
	int v;
	for (int i = h[u]; i; i = e[i].next)
	{
		v = e[i].to;
		if (v == a[u].son) continue;
		DSU(v, 1);
	}
	v = a[u].son;
	if (v) DSU(v, 0);
	vis[a[u].dep] ^= a[u].val;
	for (int i = h[u]; i; i = e[i].next)
	{
		v = e[i].to;
		if (v == a[u].son) continue;
		DFS2(v); 
	}
	for (int i = hq[u]; i; i = q[i].next)
	{
		v = q[i].to;
		if (!(vis[v] - lowbit(vis[v]))) ans[i] = 1;
	}
	if (is)
	{
		vis[a[u].dep] ^= a[u].val;
		for (int i = h[u]; i; i = e[i].next)
		{
			v = e[i].to;
			DFS2(v); 
		}
	}
}

?

当然,此题也可以用 BFS 序做( BFS 序满足同一深度结点相邻的性质),具体可以看这里







以上是关于CF 570D Tree Requests的主要内容,如果未能解决你的问题,请参考以下文章

CF570D Tree Requests

CF570D Tree Requests

Codeforces 570D TREE REQUESTS dfs???+????????????

Codeforces 570D TREE REQUESTS dfs序+树状数组 异或

CF 570 D. Tree Requests

cf570 D. Tree Requests