D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu+状压

#include <bits/stdc++.h>
using namespace std;
// #define int long long
const int N=1e6+10;
struct edge{
	int to,nxt,w;
}d[N*2]; int head[N*2],cnt=1;
void add(int u,int v,int w){	d[++cnt]=(edge){v,head[u],w},head[u]=cnt; }
typedef pair<int,int>p;
vector<p>vec[N];
int n,m,son[N],siz[N],deep[N];int ans[N],mx[1<<23],dis[1<<23];
void dfs(int u,int father,int depth,int state){
	siz[u]=1,deep[u]=depth;
    // cout<<state<<endl;
	int maxson=-1;dis[u]=state; 
	for(int i=head[u];i;i=d[i].nxt ){
		int v=d[i].to,w=d[i].w;
		if( v==father )	continue;
		dfs(v,u,depth+1,state^(1<<w));
		siz[u]+=siz[v];
		if( maxson<siz[v] )	maxson=siz[v],son[u]=v;
	}
}
void update(int u,int fa,int tag)
{
    if(tag==1) mx[dis[u]]=max(mx[dis[u]],deep[u]);
    else mx[dis[u]]=0;
    for(int i=head[u];i;i=d[i].nxt)
    {
        int x=d[i].to;
        if(x==fa) continue;
        update(x,u,tag);
    }
}
void solve(int u,int fa,int rt){
    // cout<<rt<<endl;
    int y=dis[u];
    if(mx[y]!=0) ans[rt]=max(ans[rt],deep[u]+mx[y]-2*deep[rt]);
    for(int i=0;i<22;i++){
        y=dis[u]^(1<<i);
        if(mx[y]!=0) ans[rt]=max(ans[rt],deep[u]+mx[y]-2*deep[rt]);
    }
    // cout<<ans[rt]<<endl;
    for(int i=head[u];i;i=d[i].nxt){
        int x=d[i].to;
        if(x==fa) continue;
        solve(x,u,rt);
    }
}
void dsu(int u,int father,bool keep){
    // cout<<u<<endl;
	for(int i=head[u];i;i=d[i].nxt){
        int v=d[i].to;
        if(v==father||v==son[u]) continue;
        dsu(v,u,0);ans[u]=max(ans[u],ans[v]);
    }
    if(son[u]) dsu(son[u],u,1),ans[u]=max(ans[u],ans[son[u]]);
    if(son[u]){
        if(mx[dis[u]]) ans[u]=max(ans[u],mx[dis[u]]-deep[u]);
        for(int i=0;i<22;i++) if(mx[dis[u]^(1<<i)]) ans[u]=max(ans[u],mx[dis[u]^(1<<i)]-deep[u]);
    }
    mx[dis[u]]=max(mx[dis[u]],deep[u]);
    for(int i=head[u];i;i=d[i].nxt){
        int x=d[i].to;
        if(x==father||x==son[u]) continue;
        solve(x,u,u); update(x,u,1);
    }
    if(keep==0) update(u,father,-1);
    // cout<<father<<endl;
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        char ch[2];int x;
        scanf("%d%s",&x,ch);
        add(x,i+1,ch[0]-'a');
        add(i+1,x,ch[0]-'a');
    }
    dfs(1,0,1,0);
    // cout<<1<<endl;
    // cout<<siz[1]<<endl;
    dsu(1,0,1);
    for(int i=1;i<=n;i++){
        printf("%d ",ans[i]);
    }cout<<endl;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值