题意:
有一个长度为n的数组a,每个元素a(i)在1到200之间,
且对于每一个元素a(i),都至少有一个相邻元素>=a(i),
现在数组中缺失了若干个位置的数,问原数组有多少种可能,
统计方案数,答案对998244353取模。
数据范围:n<=1e5
解法:
因为元素的范围很小,容易想到令d(i,j)表示第i个位置填j的方案数。
但是这题还涉及到相邻元素的大小关系,那么添加一维k变成d(i,j,k),
d(i,j,k)表示第i个位置填j,与前一个数关系为k的方案数即可
需要维护一个前缀和进行O(1)转移,不能O(n)暴力计算和
code:
#include<bits/stdc++.h>
using namespace std;
const int maxm=1e5+5;
const int mod=998244353;
int d[maxm][205][3];
int a[maxm];
int n;
/*
d[i][j][0/1/2]表示第i位填j,和前一位的关系为k的方案数
k=0:a[i-1]<a[i]
k=1:a[i-1]=a[i]
k=2:a[i-1]>a[i]
*/
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
//a[1],init
for(int j=1;j<=200;j++){
if(a[1]==-1||j==a[1]){//可以填j的情况
d[1][j][0]=1;
}
}
//
for(int i=2;i<=n;i++){
//
int sum=0;//维护sum(d[i-1][1到(j-1)][k])
for(int j=1;j<=200;j++){//0.<
if(a[i]==-1||j==a[i]){
d[i][j][0]=sum;
}
sum=(0LL+sum+d[i-1][j][0]+d[i-1][j][1]+d[i-1][j][2])%mod;
}
//
for(int j=1;j<=200;j++){//1.=
if(a[i]==-1||j==a[i]){
d[i][j][1]=(0LL+d[i-1][j][0]+d[i-1][j][1]+d[i-1][j][2])%mod;
}
}
//
sum=0;//维护sum(d[i-1][(j+1)到200][k])
for(int j=200;j>=1;j--){//2.>
if(a[i]==-1||j==a[i]){
d[i][j][2]=sum;
}
sum=(0LL+sum+d[i-1][j][1]+d[i-1][j][2])%mod;
}
//
}
int ans=0;
for(int j=1;j<=200;j++){//a[n-1]<=a[n]
ans=(0LL+ans+d[n][j][1]+d[n][j][2])%mod;
}
cout<<ans<<endl;
return 0;
}