一个比较显然的做法:对每棵子树用线段树维护其中的深度,线段树合并即可。
本来想用这个题学一下dsu on tree,结果还是弃疗了。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();} while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 1000010 int n,p[N],root[N],deep[N],ans[N],t=0,cnt=0; struct data{int to,nxt; }edge[N<<1]; struct data2{int l,r,x,s; }tree[N*22]; void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;} void up(int k) { if (tree[tree[k].l].s>=tree[tree[k].r].s) tree[k].s=tree[tree[k].l].s,tree[k].x=tree[tree[k].l].x; else tree[k].s=tree[tree[k].r].s,tree[k].x=tree[tree[k].r].x; } int merge(int x,int y,int l,int r) { if (!x||!y) return x|y; if (l==r) tree[x].s+=tree[y].s; else { int mid=l+r>>1; tree[x].l=merge(tree[x].l,tree[y].l,l,mid); tree[x].r=merge(tree[x].r,tree[y].r,mid+1,r); up(x); } return x; } void ins(int &k,int x,int l,int r) { if (!k) k=++cnt; if (l==r) {tree[k].s++,tree[k].x=x;return;} int mid=l+r>>1; if (x<=mid) ins(tree[k].l,x,l,mid); else ins(tree[k].r,x,mid+1,r); up(k); } void dfs(int k,int from) { for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=from) { deep[edge[i].to]=deep[k]+1; dfs(edge[i].to,k); root[k]=merge(root[k],root[edge[i].to],1,n); } ins(root[k],deep[k],1,n); ans[k]=tree[root[k]].x-deep[k]; } int main() { #ifndef ONLINE_JUDGE freopen("dsu.in","r",stdin); freopen("dsu.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(); for (int i=1;i<n;i++) { int x=read(),y=read(); addedge(x,y),addedge(y,x); } deep[1]=1;dfs(1,1); for (int i=1;i<=n;i++) printf("%d\n",ans[i]); return 0; }
原文地址:https://www.cnblogs.com/Gloid/p/9502618.html
时间: 2024-09-29 05:54:35