CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

运用点分治的思想,dsu的处理方式,每个点作为根只考虑跨过自己的最大路径长度
对于其他路径,直接由子树继承即可

开桶max_dep[i]记录子树中到根节点1路径上信息异或和为i的最大节点深度。

考虑跨过自己的最大路径长度分两种,
第一种是端点在不同子树,对于每个子树,先更新根的ans,再更新max_dep
第二种是根节点为一端点,另一端点在子树中的,统计完第一种统计这个即可

Code
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define rint register int
using namespace std;
const int maxn=5e5+5;
const int maxs=1<<22;
const int INF=0x3f3f3f3f;
int n,cnt;
int head[maxn];
int siz[maxn],son[maxn],dep[maxn];
int max_dep[maxs],dis[maxn];
int ans[maxn];
struct Edge{
	int to,next;
}e[maxn];
void Aedge(int x,int y){
	e[++cnt].to=y;
	e[cnt].next=head[x];
	head[x]=cnt;
}
void dfs1(int x){
	siz[x]=1;
	for(int i=head[x];i;i=e[i].next){
		const rint y=e[i].to;
		dis[y]^=dis[x],dep[y]=dep[x]+1;
		dfs1(y);
		siz[x]+=siz[y];
		if(!son[x]||siz[y]>siz[son[x]]) son[x]=y;
	}
}
void upd_ans(int rt,int x){
	ans[rt]=max(ans[rt],max_dep[dis[x]]+dep[x]-dep[rt]*2);
	for(int i=0;i<=21;++i) ans[rt]=max(ans[rt],max_dep[dis[x]^(1<<i)]+dep[x]-dep[rt]*2);
	for(int i=head[x];i;i=e[i].next) upd_ans(rt,e[i].to);
}
void upd_max_dep(int x){
	max_dep[dis[x]]=max(max_dep[dis[x]],dep[x]);
	for(int i=head[x];i;i=e[i].next) upd_max_dep(e[i].to);
}
void cle(int x){
	max_dep[dis[x]]=-INF;
	for(int i=head[x];i;i=e[i].next) cle(e[i].to);
}
void dfs(int x,int op){
	for(int i=head[x];i;i=e[i].next){
		const rint y=e[i].to;
		if(y!=son[x]) dfs(y,0),ans[x]=max(ans[x],ans[y]);
	}
	if(son[x]) dfs(son[x],1),ans[x]=max(ans[x],ans[son[x]]);
	for(int i=head[x];i;i=e[i].next){
		const rint y=e[i].to;
		if(y!=son[x]) upd_ans(x,y),upd_max_dep(y);
	}
	ans[x]=max(ans[x],max_dep[dis[x]]-dep[x]);
	for(int i=0;i<=21;++i) ans[x]=max(ans[x],max_dep[dis[x]^(1<<i)]-dep[x]);
	max_dep[dis[x]]=max(max_dep[dis[x]],dep[x]);
	if(!op) cle(x);
}
int main(){
	//freopen("1.in","r",stdin);
	memset(max_dep,-INF,sizeof max_dep);
	scanf("%d",&n);
	for(int i=2,x;i<=n;++i){
		char ss;
		scanf("%d %c",&x,&ss);
		Aedge(x,i),dis[i]=1<<(ss-'a');
	}
	dfs1(1);
	dfs(1,0);
	for(int i=1;i<=n;++i) printf("%d ",ans[i]);
	printf("\n");
	return 0;
}
posted @ 2020-10-27 21:48  liuzhaoxu  阅读(100)  评论(0编辑  收藏  举报