做法一:暴力跳父亲时跳到某个点时,若这个点既不是以这个点的父亲节点为根的子树内最先出现的黑点,也不是最后一个变成黑点的红点时就没有必要跳了,因为不会对答案产生贡献了(这里可能有些绕口,自己可以画图模拟一下)。
- 复杂度貌似很神奇,官方题解写的是 \(O(n)\) 。
struct node
{
int nxt,to;
}e[200001];
int head[200001],minn[200001],maxx[200001],p[200001],id[200001],fa[200001],cnt=0;//minn表示(····)最早出现,maxx表示最后一个(····)消失
void add(int u,int v)
{
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
void dfs(int x)
{
minn[x]=maxx[x]=id[x];
for(int i=head[x];i!=0;i=e[i].nxt)
{
dfs(e[i].to);
minn[x]=min(minn[x],minn[e[i].to]);
maxx[x]=max(maxx[x],maxx[e[i].to]);
}
}
int main()
{
int n,i,j,u,v,ans=0,flag;
cin>>n;
for(i=1;i<=n-1;i++)
{
cin>>u;
v=i+1;
fa[v]=u;
add(u,v);
}
for(i=1;i<=n;i++)
{
cin>>p[i];
id[p[i]]=i;
}
dfs(1);
for(i=1;i<=n;i++)
{
for(j=p[i];j!=0;j=fa[j])//暴力跳父亲
{
flag=0;
if(minn[j]==id[p[i]])
{
ans++;
flag=1;
}
if(maxx[j]==id[p[i]])
{
ans--;
flag=1;
}
if(flag==0)
{
break;
}
}
cout<<ans<<" ";
}
return 0;
}
做法二:进行差分维护一下。————隔壁@xrlong的做法
struct node
{
int nxt,to;
}e[200001];
int head[200001],minn[200001],maxx[200001],p[200001],id[200001],c[400001],cnt=0;
int lowbit(int x)
{
return (x&(-x));
}
void add(int u,int v)
{
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
void dfs(int x)
{
minn[x]=maxx[x]=id[x];
for(int i=head[x];i!=0;i=e[i].nxt)
{
dfs(e[i].to);
minn[x]=min(minn[x],minn[e[i].to]);
maxx[x]=max(maxx[x],maxx[e[i].to]);
}
}
void update(int n,int x,int key)
{
for(int i=x;i<=n;i+=lowbit(i))
{
c[i]+=key;
}
}
int getsum(int x)
{
int ans=0;
for(int i=x;i>0;i-=lowbit(i))
{
ans+=c[i];
}
return ans;
}
int main()
{
int n,i,j,u,v,ans=0,flag;
cin>>n;
for(i=1;i<=n-1;i++)
{
cin>>u;
v=i+1;
add(u,v);
}
for(i=1;i<=n;i++)
{
cin>>p[i];
id[p[i]]=i;
}
dfs(1);
for(i=1;i<=n;i++)
{
update(n,minn[i],1);
update(n,maxx[i]-1+1,-1);
}
for(i=1;i<=n;i++)
{
cout<<getsum(i)<<" ";
}
return 0;
}
struct node
{
int nxt,to;
}e[200001];
int head[200001],minn[200001],maxx[200001],p[200001],id[200001],sum[400001],cnt=0;
void add(int u,int v)
{
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
void dfs(int x)
{
minn[x]=maxx[x]=id[x];
for(int i=head[x];i!=0;i=e[i].nxt)
{
dfs(e[i].to);
minn[x]=min(minn[x],minn[e[i].to]);
maxx[x]=max(maxx[x],maxx[e[i].to]);
}
}
int main()
{
int n,i,j,u,v,ans=0;
cin>>n;
for(i=1;i<=n-1;i++)
{
cin>>u;
v=i+1;
add(u,v);
}
for(i=1;i<=n;i++)
{
cin>>p[i];
id[p[i]]=i;
}
dfs(1);
for(i=1;i<=n;i++)
{
sum[minn[i]]++;
sum[maxx[i]-1+1]--;
}
for(i=1;i<=n-1;i++)
{
ans+=sum[i];
cout<<ans<<" ";
}
cout<<"0";
return 0;
}