【题解】CF741D(DSU on TREE)
【题解】CF741D(DSU on TREE)
写一写这道题来学习学习模板
用二进制来转换一下条件,现在就是要求一下\(lowbit(x)=x\)的那些路径了。
DSU on TREE 是这样一种算法:
- 像树剖一样分出轻重链,根据那套理论可知轻边\(O(\log n)\)。
- 递归处理一个节点的所有轻儿子,并且回溯的时候将统计信息清空。
- 递归处理一个节点的那个重儿子,并且回溯的时候保留统计信息。
- 获得重儿子信息后,遍历一下所有轻儿子统计答案。
分析复杂度:对于每个点,可以被他父亲所有的轻边多遍历一次。复杂度\(O(tn \log n)\),\(t\)是加入一个信息需要的复杂度。
具体到这道题的话,就是开桶记录该二进制状态下最深深度点的深度。取\(max\)就好
//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std; typedef long long ll;
inline int qr(){
register int ret=0,f=0;
register char c=getchar();
while(c<48||c>57)f|=c==45,c=getchar();
while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
char c;
const int maxn=5e5+5,inf=1e9;
int d[maxn],cnt[1<<22|1],n,siz[maxn],son[maxn],dfn[maxn],End[maxn],arc[maxn];
int ans[maxn],dis[maxn];
vector< pair<int,int> > e[maxn];
inline void add(const int&fr,const int&to,const int&w){
e[fr].push_back({to,1<<w});
}
void predfs(const int&now){
siz[now]=1;
dfn[now]=++*dfn;
arc[*dfn]=now;
for(auto t:e[now])
d[t.first]=d[now]^t.second,dis[t.first]=dis[now]+1,predfs(t.first),siz[now]+=siz[t.first],son[now]=siz[t.first]>siz[son[now]]?t.first:son[now];
End[now]=*dfn;
}
void dfs(const int&now,const int&keep){
for(auto t:e[now])
if(t.first^son[now])
dfs(t.first,0),ans[now]=max(ans[now],ans[t.first]);
if(son[now]) dfs(son[now],1),ans[now]=max(ans[now],ans[son[now]]);
if(cnt[d[now]]) ans[now]=max(ans[now],cnt[d[now]]-dis[now]);
for(int t=0;t<22;++t)
if(cnt[d[now]^(1<<t)])
ans[now]=max(ans[now],cnt[d[now]^(1<<t)]-dis[now]);
cnt[d[now]]=max(cnt[d[now]],dis[now]);
for(auto T:e[now])
if(T.first^son[now]){
for(int t=dfn[T.first];t<=End[T.first];++t){
if(cnt[d[arc[t]]])
ans[now]=max(ans[now],cnt[d[arc[t]]]+dis[arc[t]]-dis[now]*2);
for(int i=0;i<22;++i)
if(cnt[d[arc[t]]^(1<<i)])
ans[now]=max(ans[now],cnt[d[arc[t]]^(1<<i)]+dis[arc[t]]-dis[now]*2);
}
for(int t=dfn[T.first];t<=End[T.first];++t)
cnt[d[arc[t]]]=max(cnt[d[arc[t]]],dis[arc[t]]);
}
if(!keep) for(int t=dfn[now];t<=End[now];++t) cnt[d[arc[t]]]=0;
}
int main(){
n=qr();
for(int t=2,t1;t<=n;++t){
t1=qr();
char c=getchar();
while(c<'a'||c>'z') c=getchar();
add(t1,t,c-'a');
}
predfs(1);
dfs(1,0);
for(int t=1;t<=n;++t) printf("%d ",ans[t]);
putchar('\n');
return 0;
}
博客保留所有权利,谢绝学步园、码迷等不在文首明显处显著标明转载来源的任何个人或组织进行转载!其他文明转载授权且欢迎!