标签:要求 return problem char s main text time max cpp
在一棵以结点 \(1\) 为根的树上有 \(n\) 个结点,每个结点上有一个小写字母,每个点的深度定义为根结点到该结点路径上的点数。
现在有 \(m\) 次询问 \(a,b\) ,要求输出以结点 \(a\) 为根的子树上深度为 \(b\) 的所有结点上的字母,重新排列后能否形成回文串。
其中,\(1 \leq n \leq 5 \times 10^5\) , \(1 \leq m \leq 5 \times 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(vis\left(d_i\right)\right) = 0\) 时,显然答案为 \(\texttt{Yes}\) ,否则为 \(\texttt{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\n" : "No\n");
}
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 序满足同一深度结点相邻的性质),具体可以看这里。
标签:要求 return problem char s main text time max cpp
原文地址:https://www.cnblogs.com/kcn999/p/13402268.html