Yoi #316. 最近公共祖先
题面


分析
如果i+1在i的子树内,则i+1的答案也在i的子树内,否则不行
可以通过类似并查集的方法实现,之后树上差分
#include<bits/stdc++.h>
using namespace std;
const int N=3e6+5;
int n,cnt,to[N<<1],nxt[N<<1],he[N],t[N],in[N],out[N],sgn,f[N];
inline void add(int u,int v) {
to[++cnt]=v,nxt[cnt]=he[u],he[u]=cnt;
}
void dfs(int fa,int u) {
in[u]=++sgn;
for(int e=he[u];e;e=nxt[e]) {
int v=to[e];
if(v!=fa) {
dfs(u,v);
}
}
out[u]=sgn;
}
int find(int x) {
return x==f[x]?x:f[x]=find(f[x]);
}
int main() {
freopen("ancestor.in","r",stdin);
freopen("ancestor.out","w",stdout);
scanf("%d",&n);
for(int i=2;i<=n;i++) {
int u; scanf("%d",&u);
add(u,i),add(i,u);
}
for(int i=1;i<=n;i++) f[i]=i;
dfs(0,1);
for(int i=n;i>=1;i--) {
int j=i;
while(j+1<=n&&in[i]<=in[j+1]&&in[j+1]<=out[i]) {
f[j]=j+1,j=find(j);
}
t[i]++,t[j+1]--;
}
int ans=0;
for(int i=1;i<=n;i++) {
ans+=t[i]; printf("%d\n",ans);
}
return 0;
}

浙公网安备 33010602011771号