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的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 570D TREE REQUESTS dfs???+????????????