P8290 [省选联考 2022] 填树
作者:互联网
先考虑第一问:
令 \(V_k(L)\) 为权值在 \([L,L+k]\) 中的答案。
注意到当极差为 \(d\) 时贡献会计算 \(k-d+1\) 次,利用这个特点答案可以表示为 \(\sum_{L}V_k(L)-V_{k-1}(L)\) , 下面不妨省去 \(k\)。
一条路径上的 \(V\) 为所有结点 \(V_i\) 的积,我们单独考察一下:
\[V_i(L)=\max(0,\min(r_i,L+k)-\max(l_i,L)+1) \]- \(l_i+k \le r_i\)
- \(l_i+k > r_i\)
也就是说,值域被 \(l_i,l_i-k,r_i,r_i-k\) 划分为若干区间,且每个区间上的 \(V(L)\) 为一个不超过 \(n\) 次的多项式。
那么 \(\displaystyle \sum_L V(L)\) 应为一个不超过 \(n+1\) 次的多项式。
这样的划分点有 \(\mathcal O(n)\) 个,每个区间我们利用 换根dp \(\mathcal O(n^2)\) 求出前 \(n+2\) 项然后插值即可。
下面介绍一下换根 dp 的方法,这也是 40 分做法:
首先钦定 \(1\) 为根,令 \(f_u\) 表示以 \(u\) 子树内的点作为起点,\(\sum_{v} \prod_{i \in \{v \to u\}} V_i(L)\) 的值,易得:
\[f_u=(1+\sum_{v}f_v)V_u(L) \]与此同时,我们需要知道每个点为起点时所有路径的权值和 \(g_i\),有:
\[g_v=f_v+(g_u-f_vV_u(L))V_v(L) \]注意路径被计算了两次,单点只被计算了一次,所以有:
\[V(L)=\frac{1}{2}\left(\sum_{i=1}^n g_i+V_i(L)\right) \]再考虑第二问,由于权值的贡献为和的形式所以我们考虑对每一个点单独计算贡献。
类似 \(V\) , 定义 \(W_i(L)=\max(0,\frac{1}{2}(\min(r_i,L+k)-\max(l_i,L)+1)(\max(l_i,L)+\min(r_i,L+k)))\) ,含义即为 \(i\) 在 \([L,L+k]\) 中的取值之和。
再定义 \(h_u\) 表示经过 \(u\) 的路径条数(需要确定其他点权值),那么答案可以写作:
\[\sum_{L}\sum_{u}W_u(L) h_u \]\(h\) 的定义与 \(f,g\) 的差异在于 \(u\) 的权值已经被钦定,为了对应定义 \(f_{2_u}=\frac{f_u}{V_u(L)},g_{2_u}=\frac{g_u}{V_u(L)}\)
\[h_u=\frac{1}{2}({g_{2_u}}^2-\sum_{(u,v)\in G}{f'_v}^2+1) \]注意 \(f'_v\) 的含义是以 \(u\) 为根的 \(f_v\),那么有两种情况:
-
\(v\) 在以 \(1\) 为根的树中为 \(u\) 的儿子,此时 \(f_v'=f_v\)
-
\(v\) 在以 \(1\) 为根的树中为 \(u\) 的父亲,此时 \(f_v'=g_v -f_u V_v(L)\)
事实上 \({g_{2_u}}^2\) 是 \(n-1\) 次式,那么 \(h_u\) 为 \(n-1\) 次式
,\(\sum_{L}W_u(L)h_u\) 为 \(n+2\) 次式。
总的时间复杂度即为 \(\mathcal O(n^3)\) ,需要精细实现。
卡常方面技不如人,附上在 loj 上能过的代码:
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define pii pair< int , int >
#define fi first
#define sc second
#define mp make_pair
template<typename _T>
void read( _T &x ) {
x = 0; char s = getchar();
for( ; s < '0' || s > '9' ; s = getchar() );
for( ; s >= '0' && s <= '9' ; s = getchar() ) x = x * 10 + s - '0';
}
int pb , buf[ 100 ];
template<typename _T>
void write( _T x , char ed = '\n' ) {
if( x == 0 ) buf[ ++ pb ] = 0;
for( ; x ; x /= 10 ) buf[ ++ pb ] = x % 10;
for( ; pb ; pb -- ) putchar( buf[ pb ] + '0' );
putchar( ed );
}
const int MAXN = 205 , Mod = 1e9 + 7;
inline int Add( int x , int y ) { x += y; return x >= Mod ? x - Mod : x; }
inline int Sub( int x , int y ) { x -= y; return x < 0 ? x + Mod : x; }
inline int Mul( int x , int y ) { return 1ll * x * y % Mod; }
template<typename ...Args> inline int Mul( int x , Args ...args ) { return Mul( x , Mul( args... ) ); }
inline int Qkpow( int x , int po ) { int p = 1; for( ; po ; po >>= 1 , x = Mul( x , x ) ) if( po & 1 ) p = Mul( p , x ); return p; }
inline int Inv( int x ) { return Qkpow( x , Mod - 2 ); }
int fac[ MAXN + 5 ] , ivf[ MAXN + 5 ];
void Init( ) {
fac[ 0 ] = 1;
for( int i = 1 ; i <= MAXN ; i ++ ) fac[ i ] = Mul( fac[ i - 1 ] , i );
ivf[ MAXN ] = Inv( fac[ MAXN ] );
for( int i = MAXN ; i >= 1 ; i -- ) ivf[ i - 1 ] = Mul( ivf[ i ] , i );
}
pii operator + ( pii a , pii b ) { return mp( Add( a.fi , b.fi ) , Add( a.sc , b.sc ) ); }
pii operator - ( pii a , pii b ) { return mp( Sub( a.fi , b.fi ) , Sub( a.sc , b.sc ) ); }
int px[ MAXN + 5 ] , sx[ MAXN + 5 ];
int Lagrange( int n , int *y , int L , int x0 ) {
if( x0 - L + 1 <= n ) return y[ x0 - L + 1 ];
px[ 0 ] = 1; sx[ n + 1 ] = 1;
for( int i = 1 ; i <= n ; i ++ ) px[ i ] = Mul( px[ i - 1 ] , Sub( x0 , Add( L , i - 1 ) ) );
for( int i = n ; i >= 1 ; i -- ) sx[ i ] = Mul( sx[ i + 1 ] , Sub( x0 , Add( L , i - 1 ) ) );
int ans = 0;
for( int i = 1 ; i <= n ; i ++ )
ans = Add( ans , Mul( y[ i ] , px[ i - 1 ] , sx[ i + 1 ] , ivf[ i - 1 ] , ( n - i ) & 1 ? Sub( 0 , ivf[ n - i ] ) : ivf[ n - i ] ) );
return ans;
}
int n , K , l[ MAXN + 5 ] , r[ MAXN + 5 ];
vector< int > Graph[ MAXN + 5 ];
int gs , f[ MAXN + 5 ] , g[ MAXN + 5 ] , f2[ MAXN + 5 ] , g2[ MAXN + 5 ] , par[ MAXN + 5 ];
int V1[ MAXN + 5 ] , V2[ MAXN + 5 ];
void dfs1( int u , int fa ) {
f[ u ] = 1; par[ u ] = fa;
for( int v : Graph[ u ] ) if( v != fa )
dfs1( v , u ) , f[ u ] = Add( f[ u ] , f[ v ] );
f2[ u ] = f[ u ]; f[ u ] = Mul( f[ u ] , V1[ u ] );
}
void dfs2( int u , int fa ) {
gs = Add( gs , Add( g[ u ] , V1[ u ] ) );
for( int v : Graph[ u ] ) if( v != fa ) {
g[ v ] = Add( f[ v ] , Mul( Sub( g[ u ] , Mul( f[ v ] , V1[ u ] ) ) , V1[ v ] ) );
g2[ v ] = Add( f2[ v ] , Sub( g[ u ] , Mul( f[ v ] , V1[ u ] ) ) );
dfs2( v , u );
}
}
const int iv2 = Inv( 2 );
int m , d[ 4 * MAXN + 5 ] , y_1[ MAXN + 5 ] , y_2[ MAXN + 5 ];
pii Solve( int k ) {
m = 0;
for( int i = 1 ; i <= n ; i ++ )
d[ ++ m ] = l[ i ] - k , d[ ++ m ] = l[ i ],
d[ ++ m ] = r[ i ] - k , d[ ++ m ] = r[ i ];
sort( d + 1 , d + m + 1 ); m = unique( d + 1 , d + m + 1 ) - d - 1;
d[ m ] ++;
pii ans( 0 , 0 );
for( int i = 1 ; i < m ; i ++ ) { //[di,di+1)
int L = d[ i ] , R = d[ i + 1 ] - 1;
for( int j = L ; j <= min( R , L + n + 2 ) ; j ++ ) {
gs = 0;
for( int u = 1 ; u <= n ; u ++ )
V1[ u ] = max( 0 , min( j + k , r[ u ] ) - max( j , l[ u ] ) + 1 ),
V2[ u ] = max( 0 , (int)( 1ll * ( min( j + k , r[ u ] ) - max( j , l[ u ] ) + 1 ) * ( min( j + k , r[ u ] ) + max( j , l[ u ] ) ) / 2 % Mod ) );
dfs1( 1 , 0 ); g[ 1 ] = f[ 1 ]; g2[ 1 ] = f2[ 1 ]; dfs2( 1 , 0 );
y_1[ j - L + 1 ] = Add( y_1[ j - L ] , Mul( gs , iv2 ) );
y_2[ j - L + 1 ] = y_2[ j - L ];
for( int u = 1 ; u <= n ; u ++ ) if( V1[ u ] ) {
int S = Mul( g2[ u ] , g2[ u ] );
for( int v : Graph[ u ] ) {
int d;
if( v == par[ u ] ) d = Mul( Sub( g2[ v ] , f[ u ] ) , V1[ v ] );
else d = f[ v ];
S = Sub( S , Mul( d , d ) );
}
y_2[ j - L + 1 ] = Add( y_2[ j - L + 1 ] , Mul( V2[ u ] , Mul( S + 1 , iv2 ) ) );
}
}
ans.fi = Add( ans.fi , Lagrange( n + 2 , y_1 , L , R ) );
ans.sc = Add( ans.sc , Lagrange( n + 3 , y_2 , L , R ) );
}
return ans;
}
int main( ) {
// freopen("tree.in","r",stdin);
// freopen("tree.out","w",stdout);
Init();
read( n ); read( K );
for( int i = 1 ; i <= n ; i ++ ) read( l[ i ] ) , read( r[ i ] );
for( int i = 1 , u , v ; i < n ; i ++ ) {
read( u ); read( v );
Graph[ u ].push_back( v );
Graph[ v ].push_back( u );
}
pii ans = Solve( K ) - Solve( K - 1 );
printf("%d\n%d\n", ans.fi , ans.sc );
return 0;
}
标签:P8290,pii,省选,sum,int,Add,MAXN,Mul,联考 来源: https://www.cnblogs.com/chihik/p/P8290.html