应该是树上搜索,但因为顺序不同而且情况会改变,搜索回溯什么的并不好使。
不过能发现,每一次更改对后面有影响,我们可以把影响记下来,用到线段树。
先用dfs找一遍每个点影响的范围,每走一次整个区间都加1。还是需要画一画的。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct nn
{
int to,next;
}edge[200500];
int cnt;
int head[200005];
void add(int f,int t)
{
edge[cnt].to=t;
edge[cnt].next=head[f];
head[f]=cnt++;
}
int n;
int a[100005];
int s[100005],e[100005];
int tree[100005*4];
int num;
void dfs(int u,int f)
{
s[u]=++num;
for(int i=head[u];i!=-1;i=edge[i].next)
{
if(edge[i].to==f)continue;
dfs(edge[i].to,u);
}
e[u]=num;
}
void change(int l,int r,int st,int en,int node)
{
if(st==l&&en==r)//注意,和普通的线段树并不一样
{
tree[node]++;
return ;
}
int mid=(st+en)>>1;
if(mid<l)
{
change(l,r,mid+1,en,node<<1|1);
}else if(mid>=r)//注意等号
{
change(l,r,st,mid,node<<1);
}else
{
change(l,mid,st,mid,node<<1);
change(mid+1,r,mid+1,en,node<<1|1);
}
}
int quiry(int l,int r,int x,int node)
{
if(l==r)
{
return tree[node];
}
int mid=(l+r)>>1;
if(x<=mid)return tree[node]+quiry(l,mid,x,node<<1);
else return tree[node]+quiry(mid+1,r,x,node<<1|1);
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int a,b;
scanf("%d %d",&a,&b);
add(a,b);
add(b,a);
}
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
dfs(1,0);
for(int i=1;i<=n;i++)
{
printf("%d\n",quiry(1,n,s[a[i]],1));
change(s[a[i]],e[a[i]],1,n,1);
}
}