[bzoj1782][Usaco2010 Feb]slowdown 慢慢游 dfs序+线段树

来源:互联网 发布:网站域名申请流程 编辑:程序博客网 时间:2024/05/17 18:16

1782: [Usaco2010 Feb]slowdown 慢慢游

Time Limit: 1 Sec  Memory Limit: 64 MB
[Submit][Status][Discuss]

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会放慢自己的速度,防止打扰他的朋友。 考虑如下的牧场结构(括号内的数字代表了牧场的所有者)。 

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

Sample Output

0
1
0
2
1

HINT

到一个点相当于到这个点的所有子节点答案+1, dfs序!
#include<bits/stdc++.h>using namespace std;const int N = 1000000 + 5;int last[N],cnt,ans,tot=0,n,q,root=1,in[N],out[N],dep[N],p[N],flag[N],sum[N];struct Edge{ int to,next; }e[N*2];void insert( int u, int v ){ e[++cnt].to = v; e[cnt].next = last[u]; last[u] = cnt; }void dfs( int x, int f ){in[x] = ++tot; dep[x] = dep[f] + 1;for( int i = last[x]; i; i = e[i].next )if( e[i].to ^ f )dfs( e[i].to, x );out[x] = tot;}void pushdown( int k, int l, int r ){if( flag[k] ){int mid = l + r >> 1;sum[k<<1] += flag[k] * ( mid - l + 1 ); flag[k<<1] += flag[k];sum[k<<1|1] += flag[k] * ( r - mid ); flag[k<<1|1] += flag[k];flag[k] = 0;}}void update( int k ){sum[k] = sum[k<<1] + sum[k<<1|1];}void modify( int k, int l, int r, int L, int R, int val ){if( l >= L && r <= R ){flag[k] += val; sum[k] += ( r - l + 1 ); return;}int mid = l + r >> 1;pushdown( k, l, r );if( L <= mid ) modify( k<<1, l, mid, L, R, val );if( R >  mid ) modify( k<<1|1, mid+1, r, L, R, val );update( k );}int query( int k, int l, int r, int L, int R ){if( l >= L && R >= r ){return sum[k];}pushdown( k, l, r );int mid = l + r >> 1, res = 0;if( L <= mid ) res += query( k<<1, l, mid, L, R );if( R >  mid ) res += query( k<<1|1, mid+1, r, L, R );return res;}int main(){cin>>n;for( int i = 1,u,v; i < n; i++ ){scanf("%d%d", &u, &v);insert( u, v ); insert( v, u );}for( int i = 1; i <= n; i++ ) scanf("%d", &p[i]);dep[1] = 1; dfs( 1, 0 );for( int i = 1; i <= n; i++ ){int res = query( root, 1, n, in[p[i]], in[p[i]] );modify( root, 1, n, in[p[i]], out[p[i]], 1 );printf("%d\n", res);}return 0;}


阅读全文
0 0
原创粉丝点击