題解[CF741D ...tree and ...paths]
阿新 • • 發佈:2021-10-30
題目
Sol
\(dsu \ on \ tree\)的好題。
注意到字符集只有\(a\)到\(v\),這提示我們用狀壓來做。
設\(w[u]\)為根節點到\(u\)節點路徑上的字元的奇偶情況,\(f[S]\)從\(u\)節點出發往下走,使得路徑狀態為\(S\)的最大深度。
先把\(u\)所有兒子的答案都計算好。
然後直接繼承重兒子的\(f\)陣列,並更新一次答案。
然後對於\(u\)每一個輕兒子子樹內的每一個點,先更新答案,再更新\(f\)。
更新答案:列舉每一種可能的狀態\(T(2^i||0,i\in [0,21])\),設當前列舉到的點為\(v\),則此時的答案\(ans[u]\)
code
inline void dfs1(int st,int fa){ sz[st]=1,dep[st]=dep[fa]+1,dfn[++tct]=st,pos[st]=tct,w[st]=w[fa]^(1<<val[st]); for(int i=0;i<(int)e[st].size();i++){ int ed=e[st][i]; if(ed==fa) continue; dfs1(ed,st); sz[st]+=sz[ed]; if(sz[ed]>sz[son[st]]) son[st]=ed; } return; } inline void dfs2(int st,int fa){ for(int i=0;i<(int)e[st].size();i++){ int ed=e[st][i]; if(ed==fa||ed==son[st]) continue; dfs2(ed,st); for(int j=pos[ed];j<=pos[ed]+sz[ed]-1;j++) f[w[dfn[j]]]=0; ans[st]=max(ans[st],ans[ed]); } if(son[st]) dfs2(son[st],st),ans[st]=max(ans[st],ans[son[st]]); if(f[w[st]]) ans[st]=max(ans[st],f[w[st]]-dep[st]); for(int i=0;i<22;i++) if(f[(1<<i)^w[st]]) ans[st]=max(ans[st],f[w[st]^(1<<i)]-dep[st]); f[w[st]]=max(f[w[st]],dep[st]); for(int i=0;i<(int)e[st].size();i++){ int ed=e[st][i]; if(ed==fa||ed==son[st]) continue; for(int j=pos[ed];j<=pos[ed]+sz[ed]-1;j++){ int W=w[dfn[j]],ED=dfn[j]; if(f[W]) ans[st]=max(ans[st],f[W]+dep[ED]-dep[st]-dep[st]); for(int k=0;k<22;k++) if(f[W^(1<<k)]) ans[st]=max(ans[st],f[(1<<k)^W]+dep[ED]-dep[st]-dep[st]); } for(int j=pos[ed];j<=pos[ed]+sz[ed]-1;j++) f[w[dfn[j]]]=max(f[w[dfn[j]]],dep[dfn[j]]); } return; }