[关键字]:数据结构 DFS序列
[题目大意]:有一棵树,每头牛从一号节点出发走到另一个节点上。路径上每有一个有牛的节点,那他就会减慢一次速度,问每个牛会减慢多少次速度。
//======================================================================================
[分析]:首先对树进行先序遍历,然后对每个节点编号记录每个节点v进入时的编号x和它所有子树中编号最大的那个y,这样以v为根的子树就对应了一段连续的区间。每有一个牛走到他所对应的节点v上,v的子树上所有节点的减慢次数就会+1,然后就可以利用树状数组来进行连续区间的改变和求值操作。
[代码]:
View Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=101000;
int n,tot;
int l[MAXN],r[MAXN],pos[MAXN];
int tree[MAXN];
vector<int> e[MAXN];
void DFS(int v,int fa)
{
l[v]=pos[v]=++tot;
vector<int>::iterator i;
for (i=e[v].begin();i<e[v].end();++i)
if (*i!=fa) DFS(*i,v);
r[v]=tot;
}
int Find(int k)
{
int sum=0;
while (k>0)
{
sum+=tree[k];
k-=k&(-k);
}
return sum;
}
void Insert(int k,int dat)
{
while (k<=n)
{
tree[k]+=dat;
k+=k&(-k);
}
}
int main()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
scanf("%d",&n);
int x,y;
for (int i=1;i<n;++i)
{
scanf("%d%d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
}
DFS(1,0);
// for (int i=1;i<=n;++i) printf("%d %d\n",l[i],r[i]);
for (int i=1;i<=n;++i)
{
scanf("%d",&x);
printf("%d\n",Find(pos[x]));
Insert(l[x],1);
Insert(r[x]+1,-1);
}
return 0;
}