转移考虑如果什么都不干($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;
}
```
::::