版权声明:本文为博主原创文章,你们可以随便转载 https://blog.csdn.net/Jaihk662/article/details/83826537
题意:
给你一棵n个节点的树,每条边都代表着一个字母(a~v),对于每个节点u,求出以u为根的子树中有多少条路径满足:路径上的字符重新排列后可以得到一个回文字符串
思路:
前置:dsu on tree
然后就可以思考该怎么O(n²)暴力了
因为只有22个字母,所以可以用一个数字代表当前哪些字母出现了奇数次,如果字典序第i个字母出现奇数次,那么第i位就为1,否则就为0,这样的话只要求出val[u]表示从u点到根的路径状态,如果val[u]^val[v]==0 或者val[u]^val[v]的二进制中只有1位是1,那么路径u到v就可以重排形成回文字符串
#pragma comment(linker, "/STACK:102400000,102400000")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 1000000007
vector<int> G[500005];
int val[4233333], dp[4233333];
int dep[500005], siz[500005], hson[500005], ans[500005];
void Sech1(int u, int p)
{
int i, v;
val[u] ^= val[p];
siz[u] = 1, dep[u] = dep[p]+1;
for(i=0;i<G[u].size();i++)
{
v = G[u][i];
if(v==p)
continue;
Sech1(v, u);
siz[u] += siz[v];
if(siz[v]>siz[hson[u]])
hson[u] = v;
}
}
void Init(int u)
{
int i, v;
dp[val[u]] = -1044266558;
for(i=0;i<G[u].size();i++)
{
v = G[u][i];
Init(v);
}
}
void Update(int u)
{
int i, v;
dp[val[u]] = max(dp[val[u]], dep[u]);
for(i=0;i<G[u].size();i++)
{
v = G[u][i];
Update(v);
}
}
void Gao(int u, int now)
{
int i, v;
ans[now] = max(ans[now], dep[u]+dp[val[u]]);
for(i=0;i<=21;i++)
ans[now] = max(ans[now], dep[u]+dp[val[u]^(1<<i)]);
for(i=0;i<G[u].size();i++)
{
v = G[u][i];
Gao(v, now);
}
}
void Sech2(int u)
{
int i, v;
for(i=0;i<G[u].size();i++)
{
v = G[u][i];
if(v==hson[u])
continue;
Sech2(v);
Init(v);
}
if(hson[u])
Sech2(hson[u]);
for(i=0;i<G[u].size();i++)
{
v = G[u][i];
if(v==hson[u])
continue;
Gao(v, u), Update(v);
}
dp[val[u]] = max(dp[val[u]], dep[u]);
ans[u] = max(ans[u], dep[u]+dp[val[u]]);
for(i=0;i<=21;i++)
ans[u] = max(ans[u], dep[u]+dp[val[u]^(1<<i)]);
ans[u] -= dep[u]*2;
for(i=0;i<G[u].size();i++)
{
v = G[u][i];
ans[u] = max(ans[u], ans[v]);
}
}
int main(void)
{
char ch;
int n, i, x;
scanf("%d", &n);
for(i=2;i<=n;i++)
{
scanf("%d %c", &x, &ch);
G[x].push_back(i);
val[i] = 1<<(ch-'a');
}
memset(dp, -62, sizeof(dp));
Sech1(1, 0);
Sech2(1);
for(i=1;i<=n;i++)
printf("%d ", ans[i]);
puts("");
return 0;
}