一棵根为1 的树,每条边上有一个字符(a-v共22种)。 一条简单路径被称为Dokhtar-kosh当且仅当路径上的字符经过重新排序后可以变成一个回文串。 求每个子树中最长的Dokhtar-kosh路径的长度。
如果重排后能构成回文串,那么出现奇数次的字符最多一个。用一个22位二进制数表示每一个字母出现的次数的奇偶,把一个点到根节点的路径的异或值记为$s[u]$,那么就是在子树里找到两个点使其$s$值异或之后1的个数不超过1个,那么用dsu on tree就可以了
记得最后别忘了用儿子的答案更新自己的
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #define inf -0x3f3f3f3f 6 using namespace std; 7 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 8 char buf[1<<21],*p1=buf,*p2=buf; 9 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;} 10 int read(){ 11 #define num ch-'0' 12 char ch;bool flag=0;int res; 13 while(!isdigit(ch=getc())) 14 (ch=='-')&&(flag=true); 15 for(res=num;isdigit(ch=getc());res=res*10+num); 16 (flag)&&(res=-res); 17 #undef num 18 return res; 19 } 20 inline char getch(){ 21 char ch;while((ch=getc())>'z'||ch<'a');return ch; 22 } 23 char sr[1<<21],z[20];int C=-1,Z; 24 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;} 25 void print(int x){ 26 if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x; 27 while(z[++Z]=x%10+48,x/=10); 28 while(sr[++C]=z[Z],--Z);sr[++C]=' '; 29 } 30 const int N=5e5+5; 31 int head[N],Next[N<<1],ver[N<<1],tot; 32 inline void add(int u,int v){ 33 ver[++tot]=v,Next[tot]=head[u],head[u]=tot; 34 } 35 int sz[N],d[N],son[N],s[N],ans[N],f[N*20],a[N];char c[N]; 36 int mx,n,bin[30]; 37 void dfs1(int u,int fa){ 38 sz[u]=1,d[u]=d[fa]+1,s[u]=s[fa]^bin[a[u]]; 39 for(int i=head[u];i;i=Next[i]){ 40 int v=ver[i];dfs1(v,u); 41 sz[u]+=sz[v]; 42 if(sz[son[u]]<sz[v]) son[u]=v; 43 } 44 } 45 void calc(int rt,int u){ 46 int now=s[u];cmax(mx,f[now]+d[u]-2*d[rt]); 47 if((s[u]^s[rt])==0) cmax(mx,d[u]-d[rt]); 48 for(int i=0;i<22;++i){ 49 now=bin[i]^s[u]; 50 cmax(mx,f[now]+d[u]-2*d[rt]); 51 if((s[u]^s[rt])==bin[i]) cmax(mx,d[u]-d[rt]); 52 } 53 for(int i=head[u];i;i=Next[i]) calc(rt,ver[i]); 54 } 55 void update(int u,int k){ 56 k?cmax(f[s[u]],d[u]):f[s[u]]=inf; 57 for(int i=head[u];i;i=Next[i]) update(ver[i],k); 58 } 59 void dfs2(int u,int k){ 60 for(int i=head[u];i;i=Next[i]) 61 if(ver[i]!=son[u]) dfs2(ver[i],0); 62 if(son[u]) dfs2(son[u],1); 63 mx=0;int now=s[u]; 64 cmax(mx,f[now]-d[u]); 65 for(int i=0;i<22;++i) 66 now=bin[i]^s[u],cmax(mx,f[now]-d[u]); 67 for(int i=head[u];i;i=Next[i]) 68 if(ver[i]!=son[u]) calc(u,ver[i]),update(ver[i],1); 69 ans[u]=mx; 70 if(!k){ 71 for(int i=head[u];i;i=Next[i]) update(ver[i],0); 72 f[s[u]]=inf; 73 }else cmax(f[s[u]],d[u]); 74 } 75 void spread(int u){ 76 for(int i=head[u];i;i=Next[i]){ 77 int v=ver[i];spread(v); 78 cmax(ans[u],ans[v]); 79 } 80 } 81 int main(){ 82 // freopen("testdata.in","r",stdin); 83 n=read(); 84 bin[0]=1;for(int i=1;i<=25;++i) bin[i]=bin[i-1]<<1; 85 for(int i=2;i<=n;++i){ 86 int u=read();c[i]=getch(); 87 add(u,i),a[i]=c[i]-'a'; 88 } 89 dfs1(1,0); 90 memset(f,0xef,sizeof(f)); 91 dfs2(1,0);spread(1); 92 for(int i=1;i<=n;++i) print(ans[i]); 93 return Ot(),0; 94 }