题目链接、
我居然还打过这场的cf,还补过题,还发过博客,orz,全忘了
计数dp
一脸懵b
第一维滚动数组用的
第二维枚举当前位置是哪个数
第三维0,1,2,分别表示比前面那个数小,等,大
dp里面放的是方案数
小:0,1,2都可以加
等:只要把前面那个数的0,1,2都加上。
大:加上大于这个数的数字方案数的前缀和,可以加上1,2的情况。
/*author:revolIA*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
const int maxn=100005;
ll dp[2][205][3];
ll n,a[maxn],k,sum;
int main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
for(int i=1;i<=200;i++)if(a[1] == -1||a[1] == i){
dp[k][i][0] = 1;
}
for(int i=2;i<=n;k^=1,i++){
for(int j=1;j<=200;j++){
if(a[i] == -1||a[i] == j)
dp[k^1][j][1] = (dp[k][j][0]+dp[k][j][1]+dp[k][j][2])%mod;
else dp[k^1][j][1] = 0;
}
sum = 0;
for(int j=1;j<=200;j++){
if(a[i] == -1||a[i] == j)
dp[k^1][j][0] = sum;
else dp[k^1][j][0] = 0;
sum = (sum+dp[k][j][0]+dp[k][j][1]+dp[k][j][2])%mod;
}
sum = 0;
for(int j=200;j>=1;j--){
if(a[i] == -1||a[i] == j)
dp[k^1][j][2] = sum;
else dp[k^1][j][2] = 0;
sum = (sum+dp[k][j][1]+dp[k][j][2])%mod;
}
}
ll ans = 0;
for(int i=1;i<=200;i++)ans = (ans+dp[k][i][1]+dp[k][i][2])%mod;
printf("%lld\n",ans);
return 0;
}