题意
传送门 Codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
题解
若某条路径的字符可以构成回文串,则至多一个字符数量为奇数,那么关注字符的奇偶性即可。设字符集的规模为 B B B,对字符集的奇偶性进行状态压缩,满足条件的两个字符集状态异或结果至多存在一个 1 1 1。若某个字符集的状态, O ( B ) O(B) O(B) 即可枚举满足条件的另一个状态。
dsu on tree 维护子树中各个节点字符集状态对应的最大深度,统计经过子树根节点的最长路径,最后用子孙节点的最长路径向上更新答案即可。总时间复杂度 O ( B N log N ) O(BN\log N) O(BNlogN)。
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
const int MAXN = 5E5 + 5, B = 22, SZ = 1 << B, _INF = 0xc0c0c0c0;
int N, dep[MAXN], sz[MAXN], a[MAXN];
int rec[SZ], res[MAXN], cur;
struct edge
{
int to, c;
};
vector<edge> G[MAXN];
void _max(int &x, int y) { x = max(x, y); }
void pdfs(int v, int d, int s)
{
dep[v] = d, sz[v] = 1, a[v] = s;
for (auto &e : G[v])
pdfs(e.to, d + 1, s ^ (1 << e.c)), sz[v] += sz[e.to];
}
void count(int v, int p, bool rt)
{
if (!rt)
{
for (auto &e : G[v])
count(e.to, p, 0);
}
_max(cur, dep[v] + rec[a[v]] - 2 * dep[p]);
for (int i = 0; i < B; ++i)
{
int t = a[v] ^ (1 << i);
_max(cur, dep[v] + rec[t] - 2 * dep[p]);
}
}
void add(int v)
{
_max(rec[a[v]], dep[v]);
for (auto &e : G[v])
add(e.to);
}
void del(int v)
{
rec[a[v]] = _INF;
for (auto &e : G[v])
del(e.to);
}
void dfs(int v, bool keep)
{
int mx = -1, ch = -1;
for (auto &e : G[v])
if (sz[e.to] > mx)
mx = sz[e.to], ch = e.to;
for (auto &e : G[v])
if (e.to != ch)
dfs(e.to, 0);
if (ch != -1)
dfs(ch, 1);
cur = 0;
for (auto &e : G[v])
if (e.to != ch)
count(e.to, v, 0), add(e.to);
count(v, v, 1);
_max(rec[a[v]], dep[v]);
res[v] = cur;
if (!keep)
del(v);
}
void get_res(int v)
{
for (auto &e : G[v])
{
get_res(e.to);
res[v] = max(res[v], res[e.to]);
}
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> N;
for (int i = 1; i < N; ++i)
{
int p;
char c;
cin >> p >> c;
G[p - 1].pb({i, c - 'a'});
}
pdfs(0, 0, 0);
memset(rec, 0xc0, sizeof(rec));
dfs(0, 0);
get_res(0);
for (int i = 0; i < N; ++i)
cout << res[i] << (i + 1 == N ? '\n' : ' ');
return 0;
}