bzoj3011 可并堆

我们可以遍历得出每个节点到根节点的距离h,然后用可并堆进行维护。树形dp

我用的是pairing heap

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<queue>
 4 using namespace std ; 
 5 
 6 struct node {
 7     long long value ;
 8     node * brother ; 
 9     node * child ; 
10     node ( const long long value ) : value ( value ) , 
11     brother ( 0 ) , child ( 0 ) {} ;
12 } ;
13 
14 node * merge ( node * a , node * b ) {
15     if ( a == 0 ) return b ; 
16     if ( b == 0 ) return a ;
17     if ( a -> value < b -> value ) swap ( a , b ) ; 
18     b -> brother = a -> child ; 
19     a -> child = b ; 
20     a -> brother = 0 ;
21     return a ;
22 }
23 
24 node * pop ( node * a ) {
25     node * o = a -> child ; 
26     delete a ; 
27     if ( o == 0 ) return 0 ;
28     static queue < node * > q ; 
29     while ( ! q . empty () ) q . pop () ;
30     while ( o ) {
31         q . push ( o ) ; 
32         o = o -> brother ; 
33     }
34     while ( q . size () > 1u ) {
35         node * a = q . front () ; 
36         q . pop () ; 
37         node * b = q . front () ; 
38         q . pop () ; 
39         q . push ( merge ( a , b ) ) ;
40     }
41     return q . front () ; 
42 }
43 
44 
45 const int MAXN = 200000 + 20 ; 
46 int pa [ MAXN ] ;
47 long long l [ MAXN ] ;
48 long long h [ MAXN ] ;
49 int size [ MAXN ] ;
50 int N ;
51 long long L ;
52 node * heap [ MAXN ] ;
53 
54 int main () {
55     scanf ( "%d%lld" , & N , & L ) ; 
56     for ( int i = 2 ; i <= N ; ++ i ) 
57         scanf ( "%d%lld" , & pa [ i ] , & l [ i ] ) ; 
58     for ( int i = 2 ; i <= N ; ++ i ) h [ i ] = l [ i ] + h [ pa [ i ] ] ;
59     for ( int i = 1 ; i <= N ; ++ i ) {
60         heap [ i ] = new node ( h [ i ] ) ; 
61         size [ i ] = 1 ; 
62     }
63     for ( int i = N ; i >= 2 ; -- i ) {
64         while ( heap [ i ] -> value - h [ i ] > L ) {
65             heap [ i ] = pop ( heap [ i ] ) ; 
66             size [ i ] -- ; 
67         }
68         heap [ pa [ i ] ] = merge ( heap [ pa [ i ] ] , heap [ i ] ) ; 
69         size [ pa [ i ] ] += size [ i ] ;
70     }
71     while ( heap [ 1 ] -> value - h [ 1 ] > L ) {
72         heap [ 1 ] = pop ( heap [ 1 ] ) ; 
73         size [ 1 ] -- ; 
74     }
75     for ( int i = 1 ; i <= N ; ++ i ) 
76         printf ( "%d\n" , size [ i ] ) ; 
77     return 0 ; 
78 }

 

转载于:https://www.cnblogs.com/Christopher-Cao/p/5341281.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值