题解:CF2234E Vlad, Misha and Two Arrays
MaxBlazeResFire · · 题解
线性做法。
显然对于点
考虑现在在建树
那么一路上每个右子树
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define mod 1000000007
#define MAXN 500005
int n,a[MAXN],fac[MAXN],inv[MAXN],ifac[MAXN],Fa[MAXN],siz[MAXN],vis[MAXN];
vector<int> E[MAXN];
inline int C( int n , int m ){ return n >= m && n >= 0 && m >= 0 ? fac[n] * ifac[m] % mod * ifac[n - m] % mod : 0; }
inline int read(){
int x = 0; char ch = getchar();
while( ch < '0' || ch > '9' ) ch = getchar();
while( ch >= '0' && ch <= '9' ) x = x * 10 + ch - 48,ch = getchar();
return x;
}
int Ans = 1,flag = 0,Cnt = 0,Snt = 0;
inline void clear(){
for( int i = 1 ; i <= n ; i ++ ) Fa[i] = 0,E[i].clear(),siz[i] = vis[i] = a[i] = 0;
Ans = 1,flag = Cnt = Snt = 0;
}
int build( int t ){
Cnt ++; if( Cnt > n ) return flag = 0;
if( vis[t] ) return flag = 0;
Snt ++,vis[t] = 1;
siz[t] = 1;
int L = 0,p = 1;
for( int v : E[t] ){
int res = build( v );
if( !res ) return flag = 0;
p *= ( siz[v] + 1 ),siz[t] += siz[v];
if( !L ) L = siz[v];
}
Ans = Ans * C( siz[t] - 1 , L ) % mod;
// assert( t <= n );
if( p != a[t] ) return flag = 0;
return 1;
}
//找左偏链
int BL( int l , int r ){
//已知 [l,r] 是一棵子树
if( l == r ) return a[l] == 1 ? l : flag = 0;
int p = l;
while( 1 ){
assert( p <= n );
if( a[p] % ( p - l + 1 ) ) return flag = 0;
int rsiz = a[p] / ( p - l + 1 );
int nxt = p + rsiz;
if( nxt <= p ) return flag = 0;
if( nxt <= r ) Fa[p] = nxt;
//这里致命问题:p>n 的话也会进去
if( nxt > r + 1 ){ return flag = 0; }
if( nxt - p > 1 ){
int res = BL( p + 1 , nxt - 1 );
if( !res ) return flag = 0;
Fa[res] = p;
}
if( nxt == r + 1 ) return p;
else if( nxt > r + 1 ) return flag = 0;
p = nxt;
}
}
inline void solve(){
flag = 1,Cnt = 0;
n = read();
int S = 0;
for( int i = 1 ; i <= n ; i ++ ) a[i] = read(),S += a[i];
if( S != n * ( n + 1 ) / 2 ){ puts("0"); clear(); return; }
int rt = BL( 1 , n );
if( !rt || !flag ){ puts("0"); clear(); return; }
// int t
for( int i = 1 ; i <= n ; i ++ ){
if( Fa[i] ) E[Fa[i]].emplace_back( i );
else if( i != rt ){ puts("0"); clear(); return; }
}
for( int i = 1 ; i <= n ; i ++ ) assert( E[i].size() <= 2 );
Ans = 1,Snt = 0;
int res = build( rt );
if( !res || siz[rt] != n || !flag || Snt != n ){ puts("0"); clear(); return; }
printf("%lld\n",Ans); clear(); return;
}
signed main(){
fac[0] = inv[1] = ifac[0] = 1;
for( int i = 1 ; i < MAXN ; i ++ ) fac[i] = fac[i - 1] * i % mod;
for( int i = 2 ; i < MAXN ; i ++ ) inv[i] = ( mod - mod / i ) * inv[mod % i] % mod;
for( int i = 1 ; i < MAXN ; i ++ ) ifac[i] = ifac[i - 1] * inv[i] % mod;
int t = read();
while( t -- ) solve();
return 0;
}