空间不知道哪里炸了啊/yun
#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std ;
#define int long long
int read ( ) {
char ch = getchar ( ) ;
int x = 0 , f = 0 ;
while ( ch < '0' || ch > '9' )
f = ch == '-' , ch = getchar ( ) ;
while ( ch >= '0' && ch <= '9' )
x = x * 10 + ch - 48 , ch = getchar ( ) ;
return x * ( f ? -1 : 1 ) ;
}
const int N = 100005 ;
int n , m , a[N] , b[N] , c[N] , ax , rt , siz[N] , tot ;
bool vis[N] ;
vector < int > ed[N] ;
void dfs0 ( int x , int la , int sz ) {
siz [ x ] = 1 ;
int axx = 0 ;
for ( int y : ed [ x ] ) {
if ( y == la || vis [ y ] ) continue ;
dfs0 ( y , x , sz ) ;
siz [ x ] += siz [ y ] ;
axx = max ( axx , siz [ y ] ) ;
}
axx = max ( axx , sz - siz [ x ] ) ;
if ( axx < ax ) ax = axx , rt = x ;
}
int sign ( int x ) { return x < 0 ? -1 : x > 0 ; }
struct Point {
int x , y ;
Point ( int _x = 0 , int _y = 0 ) :
x ( _x ) , y ( _y ) { }
Point operator + ( const Point u ) const { return { u .x + x , u .y + y } ; }
Point operator - ( const Point u ) const { return { x - u .x , y - u .y } ; }
bool operator < ( const Point u ) const { return x == u .x ? y < u .y : x < u .x ; }
int det ( Point u ) { return x * u .y - y * u .x ; }
} ;
vector < Point > v0[N] , v1[N] , vc , ans , ret ;
int crossop ( Point q , Point p1 , Point p2 ) {
return sign ( ( p1 - q ) .det ( p2 - q ) ) ;
}
int a0 , b0 , a1 , b1 ;
void dfs ( int x , int la ) {
a0 += a [ x ] , b0 += b [ x ] ;
a1 += a [ x ] , b1 += b [ x ] ;
if ( c [ x ] )
v1 [ tot ] .push_back ( Point ( a1 , b1 ) ) ;
else
v0 [ tot ] .push_back ( Point ( a0 , b0 ) ) ;
siz [ x ] = 1 ;
for ( int y : ed [ x ] ) {
if ( y == la || vis [ y ] ) continue ;
dfs ( y , x ) ;
siz [ x ] += siz [ y ] ;
}
a0 -= a [ x ] , b0 -= b [ x ] ;
a1 -= a [ x ] , b1 -= b [ x ] ;
}
vector < Point > convex ( vector < Point > ps ) {
int n = ps .size ( ) , k = 0 ;
if ( n <= 1 ) return ps ;
sort ( ps .begin ( ) , ps .end ( ) ) ;
vector < Point > qs ( n ) ;
for ( int i = 0 ; i < n ; qs [ k ++ ] = ps [ i ++ ] )
while ( k > 1 && crossop ( qs [ k - 2 ] , qs [ k - 1 ] , ps [ i ] ) >= 0 ) -- k ;
qs .resize ( k ) ;
return qs ;
}
vector < Point > conmerge ( vector < Point > ps , vector < Point > qs ) {
int cnt = 0 , sp = ps .size ( ) , sq = qs .size ( ) ;
if ( ! sp || ! sq ) return { } ;
vector < Point > res ( sp + sq + 1 ) ;
res [ 0 ] = ps [ 0 ] + qs [ 0 ] ;
int i = 0 , j = 0 ;
Point cp , cq ;
while ( i < sp - 1 && j < sq - 1 ) {
++ cnt ;
cp = ps [ i + 1 ] - ps [ i ] ;
cq = qs [ j + 1 ] - qs [ j ] ;
if ( sign ( cp .det ( cq ) ) <= 0 )
res [ cnt ] = res [ cnt - 1 ] + cp , ++ i ;
else
res [ cnt ] = res [ cnt - 1 ] + cq , ++ j ;
}
while ( i < sp - 1 ) ++ cnt , res [ cnt ] = res [ cnt - 1 ] + ps [ i + 1 ] - ps [ i ] , ++ i ;
while ( j < sq - 1 ) ++ cnt , res [ cnt ] = res [ cnt - 1 ] + qs [ j + 1 ] - qs [ j ] , ++ j ;
res .resize ( cnt + 1 ) ;
return res ;
}
struct cmp {
bool operator ( ) ( int x , int y ) {
return v0 [ x ] .size ( ) + v1 [ x ] .size ( ) < v1 [ y ] .size ( ) + v0 [ y ] .size ( ) ;
}
} ;
priority_queue < int , vector < int > , cmp > q ;
void solve ( int x ) {
vis [ x ] = 1 ;
tot = 1 ;
v0 [ 1 ] .clear ( ) , v1 [ 1 ] .clear ( ) ;
if ( c [ x ] )
v1 [ 1 ] .push_back ( Point ( a [ x ] , b [ x ] ) ) ;
else
v0 [ 1 ] .push_back ( Point ( a [ x ] , b [ x ] ) ) ;
q .push ( 1 ) ;
for ( int y : ed [ x ] ) {
if ( vis [ y ] ) continue ;
++ tot ;
v0 [ tot ] .clear ( ) , v1 [ tot ] .clear ( ) ;
if ( c [ x ] )
a0 = b0 = 0 , a1 = a [ x ] , b1 = b [ x ] ;
else
a0 = a [ x ] , b0 = b [ x ] , a1 = b1 = 0 ;
dfs ( y , x ) ;
v0 [ tot ] = convex ( v0 [ tot ] ) ;
v1 [ tot ] = convex ( v1 [ tot ] ) ;
q .push ( tot ) ;
}
ret .clear ( ) ;
while ( tot > 1 ) {
int x = q .top ( ) ; q .pop ( ) ;
int y = q .top ( ) ; q .pop ( ) ;
vc = conmerge ( v0 [ x ] , v1 [ y ] ) ;
for ( auto u : vc ) ret .push_back ( u ) ;
vc = conmerge ( v1 [ x ] , v0 [ y ] ) ;
for ( auto u : vc ) ret .push_back ( u ) ;
for ( auto u : v0 [ x ] ) v0 [ y ] .push_back ( u ) ;
for ( auto u : v1 [ x ] ) v1 [ y ] .push_back ( u ) ;
v0 [ y ] = convex ( v0 [ y ] ) ;
v1 [ y ] = convex ( v1 [ y ] ) ;
q .push ( y ) ; -- tot ;
}
while ( ! q .empty ( ) ) q .pop ( ) ;
ret = convex ( ret ) ;
for ( auto u : ret ) ans .push_back ( u ) ;
// puts ( "\n" ) ;
for ( int y : ed [ x ] ) {
if ( vis [ y ] ) continue ;
ax = n + 1 ;
dfs0 ( y , x , siz [ y ] ) ;
solve ( rt ) ;
}
}
bool check ( Point u , int p ) {
return u .y < p * u .x ;
}
int calc ( Point u , int x ) {
return u .y - x * u .x ;
}
signed main ( ) {
// freopen ( "data.in" , "r" , stdin ) ;
n = read ( ) , m = read ( ) ;
for ( int i = 1 ; i <= n ; ++ i ) a [ i ] = read ( ) ;
for ( int i = 1 ; i <= n ; ++ i ) b [ i ] = read ( ) ;
for ( int i = 1 ; i <= n ; ++ i ) c [ i ] = read ( ) ;
for ( int i = 1 ; i < n ; ++ i ) {
int u = read ( ) , v = read ( ) ;
ed [ u ] .push_back ( v ) ;
ed [ v ] .push_back ( u ) ;
}
ax = n + 1 ;
dfs0 ( 1 , 0 , n ) ;
solve ( rt ) ;
ans = convex ( ans ) ;
int R = ans .size ( ) ;
while ( m -- ) {
int k = - read ( ) ;
if ( R == 1 ) {
cout << ans [ 0 ] .y - k * ans [ 0 ] .x << "\n" ;
continue ;
}
int l = 0 , r = R - 2 , mid ;
// int res = 0 ;
// for ( int i = 0 ; i < R ; ++ i ) res = max ( res , calc ( ans [ i ] , k ) ) ;
while ( l < r ) {
mid = ( l + r ) >> 1 ;
if ( check ( ans [ mid + 1 ] - ans [ mid ] , k ) )
r = mid ;
else l = mid + 1 ;
}
if ( r == R - 2 )
cout << max ( calc ( ans [ r ] , k ) , calc ( ans [ r + 1 ] , k ) ) << "\n" ;
else cout << calc ( ans [ r ] , k ) << "\n" ;
}
return 0 ;
}