1. 程式人生 > >Codeforces Round #383 (Div. 1): D. Arpa’s letter-marked tree…(dsu on tree+狀壓)

Codeforces Round #383 (Div. 1): D. Arpa’s letter-marked tree…(dsu on tree+狀壓)

 

題意:

給你一棵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;
}