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 }