codeforces div518 D - Array Without Local Maximums - [dp]

题意:给定一个长度为 n(n≤1e5) 的数组 a[1:n],a[i] 的值域为 1 到 200,且每个数的旁边必须有一个不小于它的数。而有些数字被擦掉了,现在问共有多少种可行的填充方案。

题解:

看到这题第一感觉就dfs暴力搜索,然而时间复杂度显然不行,因此考虑dp。
考虑 dp[i][x][0,1,2] 的表示的状态为已经确定了第 i 个数字为 x,而 0,1,2 分别表示第 i−1 个数 w 是小于、等于或大于 x。其存储的值是其状态下的方案数。
那么就有状态转移方程(当然这是建立在第 i+1 位可以填 y 的前提下的):
dp[i+1][y][0]=∑x=1y−1dp[i][x][0,1,2]dp[i+1][y][1]=dp[i][y][0,1,2]dp[i+1][y][2]=∑x=y+1200dp[i][x][1,2]
边界条件,考虑到第 1 个数左边是空的,相当于左边是一个更小的数,因此有(依然是建立在第一位能填入 x 的前提下):

dp[1][x][0]=1
dp[1][x][1]=0
dp[1][x][2]=0

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e5+5;
int n,a[maxn];
ll sum,dp[maxn][203][3];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int x=1;x<=200;x++)
    {
        if(a[1]!=-1 && a[1]!=x) dp[1][x][0]=dp[1][x][1]=dp[1][x][2]=0;
        else dp[1][x][0]=1, dp[1][x][1]=dp[1][x][2]=0;
    }
    for(int i=2;i<=n;i++)
    {
        sum=0;
        for(int y=1;y<=200;y++)
        {
            if(a[i]!=-1 && a[i]!=y) dp[i][y][0]=0;
            else dp[i][y][0]=sum;
            sum+=(dp[i-1][y][0]+dp[i-1][y][1]+dp[i-1][y][2])%mod;
            sum%=mod;
        }

        for(int y=1;y<=200;y++)
        {
            if(a[i]!=-1 && a[i]!=y) dp[i][y][1]=0;
            else dp[i][y][1]=(dp[i-1][y][0]+dp[i-1][y][1]+dp[i-1][y][2])%mod;
        }

        sum=0;
        for(int y=200;y>=1;y--)
        {
            if(a[i]!=-1 && a[i]!=y) dp[i][y][2]=0;
            else dp[i][y][2]=sum;
            sum+=(dp[i-1][y][1]+dp[i-1][y][2])%mod;
            sum%=mod;
        }
    }
    ll ans=0;
    for(int x=1;x<=200;x++) ans+=(dp[n][x][1]+dp[n][x][2])%mod, ans%=mod;
    cout<<ans<<endl;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值