codeforces Array Without Local Maximums

题目描述

题解

考虑dp,设f[i][j][0/1]表示前i个数,第i个数为j,第i-1个数小于/大于等于j的方案数

考虑转移,假设第i个数选j,第i-1个数选k,则
1.$k>j$ $f[i-1][k][1]=>f[i-1][j][1]$
2.$k=j$ $f[i-1][k][0]+f[i-1][k][1]=>f[i-1][j][1]$
3.$k<j$ $f[i-1][k][0]+f[i-1][k][1]=>f[i-1][j][0]$

前缀和优化即可,效率: $O(200n)$

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5,P=998244353;
int n,f[205][2],pr[205][2],sf[205][2],a[N],s;
int X(int x){return x>=P?x-P:x;}
int main(){
    cin>>n;
    for (int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    if (~a[1]) f[a[1]][0]=1;
    else for (int i=1;i<=200;i++) f[i][0]=1;
    for (int i=2;i<=n;i++){
        for (int j=1;j<=200;j++)
            pr[j][0]=X(pr[j-1][0]+f[j][0]),
            pr[j][1]=X(pr[j-1][1]+f[j][1]);
        for (int j=200;j;j--)
            sf[j][0]=X(sf[j+1][0]+f[j][0]),
            sf[j][1]=X(sf[j+1][1]+f[j][1]);
        for (int j=1;j<=200;j++){
            f[j][0]=f[j][1]=0;
            if ((~a[i]) && a[i]!=j) continue;
            f[j][1]=X(pr[j][0]-pr[j-1][0]+P);
            f[j][1]=X(f[j][1]+X(pr[j][1]-pr[j-1][1]+P));
            f[j][1]=X(f[j][1]+sf[j+1][1]);
            f[j][0]=X(pr[j-1][0]+pr[j-1][1]);
        }
    }
    for (int i=1;i<=200;i++)
        s=X(s+f[i][1]);
    cout<<s<<endl;return 0;
}

猜你喜欢

转载自www.cnblogs.com/xjqxjq/p/12305657.html