题解:AT_abc457_f [ABC457F] Second Gap

· · 题解

转移考虑如果什么都不干($D_{i-1}=D_i$),转移 $$f_{i-1,j,0}\leftarrow f_{i,j,0}\times(n-i)$$ $$f_{i-1,j,1}\leftarrow f_{i,j,1}\times(n-i)$$ 如果不满足,什么都不做,实现起来视作乘 $0$。 如果更新次大值或最大值,都要求 $D_{i-1}=j-(i-1)$,更新 $$f_{i-1,j,0}\leftarrow f_{i,j,0}+f_{i,j,1}$$ $$f_{i-1,i-1,1}\leftarrow f_{i,j,0}+f_{i,j,1}$$ 全局乘,单点查询,单点修改,注意到有全局乘 $0$ 的操作,需要线段树维护。$O(n\log n)$。 ::::success[Code] ```cpp #include<bits/stdc++.h> using namespace std; //一眼线段树优化 dp #define int long long #define MAXN 200005 #define mod 998244353 int n,m,q,D[MAXN]; 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; } inline void chkadd( int &x , int k ){ x += k; if( x >= mod ) x -= mod; } struct segtree{ int tag[MAXN << 2],f[MAXN << 2]; void build( int t , int l , int r ){ tag[t] = 1,f[t] = 0; if( l == r ) return; int mid = ( l + r ) >> 1; build( t << 1 , l , mid ),build( t << 1 | 1 , mid + 1 , r ); } inline void update( int t , int k ){ f[t] = f[t] * k % mod,tag[t] = tag[t] * k % mod; } inline void push_down( int t ){ if( tag[t] != 1 ){ update( t << 1 , tag[t] ); update( t << 1 | 1 , tag[t] ); tag[t] = 1; } } void modify( int t , int l , int r , int x , int k ){ if( l == r ){ chkadd( f[t] , k ); return; } push_down( t ); int mid = ( l + r ) >> 1; if( x <= mid ) modify( t << 1 , l , mid , x , k ); else modify( t << 1 | 1 , mid + 1 , r , x , k ); } int query( int t , int l , int r , int x ){ if( l == r ) return f[t]; push_down( t ); int mid = ( l + r ) >> 1; if( x <= mid ) return query( t << 1 , l , mid , x ); else return query( t << 1 | 1 , mid + 1 , r , x ); } }T[2]; inline void solve(){ scanf("%lld",&n); for( int i = 1 ; i < n ; i ++ ) scanf("%lld",&D[i]); if( D[n - 1] != 1 ){ puts("0"); return; } T[0].build( 1 , 1 , n ),T[1].build( 1 , 1 , n ); T[0].modify( 1 , 1 , n , n , 1 ); T[1].modify( 1 , 1 , n , n - 1 , 1 ); for( int i = n - 1 ; i >= 2 ; i -- ){ int ij = D[i - 1] + ( i - 1 ),d1 = 0; if( ij <= n ){ chkadd( d1 , T[0].query( 1 , 1 , n , ij ) ); chkadd( d1 , T[1].query( 1 , 1 , n , ij ) ); } int ij2 = i - 1 + D[i - 1],d2 = 0; if( ij2 <= n ) d2 = T[0].query( 1 , 1 , n , ij2 ); int ij3 = i - 1 + D[i - 1],d3 = 0; if( ij3 <= n ) d3 = T[1].query( 1 , 1 , n , ij3 ); if( D[i] == D[i - 1] ){ T[0].tag[1] = T[0].tag[1] * ( n - i ) % mod; T[1].tag[1] = T[1].tag[1] * ( n - i ) % mod; } else T[0].tag[1] = T[1].tag[1] = 0; if( ij <= n ) T[0].modify( 1 , 1 , n , ij , d1 ); if( ij2 <= n ) T[1].modify( 1 , 1 , n , i - 1 , d2 ); if( ij3 <= n ) T[1].modify( 1 , 1 , n , i - 1 , d3 ); int c0 = 0,c1 = 0; // cerr << T[0].query( 1 , 1 , n , n ) << "\n"; // for( int i = 1 ; i <= n ; i ++ ) chkadd( c0 , T[0].query( 1 , 1 , n , i ) ); // for( int i = 1 ; i <= n ; i ++ ) chkadd( c1 , T[1].query( 1 , 1 , n , i ) ); // cerr << i << " " << c0 << " " << c1 << "\n"; } int ans = 0; for( int i = 1 ; i <= n ; i ++ ) chkadd( ans , T[0].query( 1 , 1 , n , i ) ); for( int i = 1 ; i <= n ; i ++ ) chkadd( ans , T[1].query( 1 , 1 , n , i ) ); printf("%lld\n",ans); } signed main(){ int t = 1; while( t -- ) solve(); return 0; } ``` ::::