Description
每天Farmer John的N头奶牛(1 <= N <= 100000,编号1…N)从粮仓走向他的自己的牧场。牧场构成了一棵树,粮仓在1号牧场。恰好有N-1条道路直接连接着牧场,使得牧场之间都恰好有一条路径相连。第i条路连接着A_i,B_i,(1 <= A_i <= N; 1 <= B_i <= N)。奶牛们每人有一个私人牧场P_i (1 <= P_i <= N)。粮仓的门每次只能让一只奶牛离开。耐心的奶牛们会等到他们的前面的朋友们到达了自己的私人牧场后才离开。首先奶牛1离开,前往P_1;然后是奶牛2,以此类推。当奶牛i走向牧场P_i时候,他可能会经过正在吃草的同伴旁。当路过已经有奶牛的牧场时,奶牛i会放慢自己的速度,防止打扰他的朋友。 考虑如下的牧场结构(括号内的数字代表了牧场的所有者)。![](http://www.lydsy.com/JudgeOnline/images/1782.jpg)
![](http://www.lydsy.com/JudgeOnline/images/1782.jpg)
Input
* 第1行 : 一个正整数N * 第2…N行: 第i+1行包括一对正整数A_i,B_i * 第N+1..N+N行: 第 N+i行 包括一个正整数: P_i
Output
* 第一行到第N行:第i行表示第i只奶牛需要被放慢的次数
Sample Input
5
1 4
5 4
1 3
2 4
4
2
1
5
3
1 4
5 4
1 3
2 4
4
2
1
5
3
Sample Output
0
1
0
2
1
1
0
2
1
dfs的时候记录一下此时比当前权值小的点有多少,每次dfs完一棵子树之后记得要减去自身。求和及修改用树状数组维护即可。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 const int N=1e5+10; 5 int n,first[N],tot=0,p[N],ans[N],t[N]; 6 struct node{ 7 int ne,to; 8 }e[N*2]; 9 int lowbit(int x){return x&-x;} 10 int read(){ 11 int ans=0,f=1;char c=getchar(); 12 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 13 while(c>='0'&&c<='9'){ans=ans*10+c-48;c=getchar();} 14 return ans*f; 15 } 16 void ins(int u,int v){e[++tot]=(node){first[u],v};first[u]=tot;} 17 int sum(int x){ 18 int ans=0; 19 for(int i=x;i;i-=lowbit(i)){ 20 ans+=t[i]; 21 } 22 return ans; 23 } 24 void up(int x,int val){for(x;x<=n;x+=lowbit(x))t[x]+=val;} 25 void dfs(int x,int fa){ 26 ans[p[x]]=sum(p[x]);up(p[x],1); 27 for(int i=first[x];i;i=e[i].ne){ 28 int to=e[i].to; 29 if(to!=fa)dfs(to,x); 30 } 31 up(p[x],-1); 32 } 33 int main(){ 34 n=read(); 35 for(int i=1,a,b;i<=n-1;i++){ 36 a=read();b=read();ins(a,b);ins(b,a); 37 } 38 for(int i=1;i<=n;i++)p[read()]=i; 39 dfs(1,0); 40 for(int i=1;i<=n;i++)printf("%d ",ans[i]); 41 return 0; 42 } 43