#4710. 并
题解
挺妙的一道题
考虑 $s_u$ 集合大小,如果 $(u,v)$ 合并的话,那就是 $s_u+s_v-s_u∩s_v$ ,然后可以发现这个交集就是上一次这条边合并后的 $s_u$的大小
然后我们考虑怎么知道 $u$ 能延伸的范围,发现我们反过来做,每次合并的话上述式子的意义就是 $u$ 的范围+ $v$ 的范围-重复的范围,发现重复的范围就是下一次他们合并的时候的大小
效率: $O(n+m)$
代码
#include <bits/stdc++.h> using namespace std; const int N=5e5+5; int n,m,U[N],V[N],p[N],s[N],f[N]; int main(){ cin>>n>>m;s[n]=1; for (int i=1;i<n;i++) scanf("%d%d",&U[i],&V[i]),s[i]=1; for (int i=1;i<=m;i++) scanf("%d",&p[i]); for (int i=m,u,v;i;i--) u=U[p[i]],v=V[p[i]], f[p[i]]=s[u]=s[v]=s[u]+s[v]-f[p[i]]; for (int i=1;i<=n;i++) printf("%d",s[i]),putchar(i<n?' ':'\n'); return 0; }