CodeForces - 1067A Array Without Local Maximums
程序员文章站
2022-05-21 12:10:37
...
题目来源:http://codeforces.com/problemset/problem/1067/A
题意:给你一个序列,序列中的-1可以是[1,200]中的任意数,问该数列有多少种情况满足任意a[i]<=max(a[i-1],a[i+1])。
思路:dp。首先定义状态f[i][j][k]表示前i个数,第i个数是j的方案数,其中k=0表示a[i]==a[i-1],k=1表示a[i]<a[i-1]。k=2表示a[i]>a[i-1]。转移的时候如果a[i]是-1就从1到200枚举,否则只更新f[i][a[i]]。
但这样数组为1e5*200*3=6e7。数组开不下。考虑到f[i]只和f[i-1]有关,这样第一维可以用滚动数组优化掉。
代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#define ll long long
#define ull unsigned long long
#define BUG cout<<"*************************\n"
using namespace std;
ll gcd(ll a, ll b) {
return b == 0 ? a : gcd(b, a % b);
}
ll lcm(ll a, ll b) {
return a / gcd(a, b) * b;
}
ll pow_mod(ll a, ll b, ll mod) {
ll ans = 1;
while (b) {
if (b & 1)ans = (ans * a) % mod;
a = (a * a) % mod;
b >>= 1;
}
return ans % mod;
}
bool is_prime(ll n) {
if (n == 1 || n == 2)return 1;
for (int i = 2; i <= sqrt(n); ++i)
if (n % i == 0)return 0;
return 1;
}
const ll mod = 998244353;
const int maxn = 4e5 + 10;
const int maxm = 1e6 + 10000;
const double eps = 1e-8;
int n, a[maxn];
ll up_sum[maxn][3], down_sum[maxn][3];
ll f[2][211][3];
int main() {
/*ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);*/
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
}
if (a[1] == -1) {
for (int i = 1; i <= 200; ++i) {
f[1][i][2] = 1;
}
} else {
f[1][a[1]][2] = 1;
}
// 1 a[i]<a[i-1]
// 2 a[i]>a[i-1]
for (int i = 2; i <= n; ++i) {
for (int j = 1; j <= 200; ++j)
f[i & 1][j][0] = f[i & 1][j][1] = f[i & 1][j][2] = 0;
if (a[i] == -1) {
if (a[i - 1] == -1) {
for (int j = 1; j <= 200; ++j) {
(up_sum[j][0] = up_sum[j - 1][0] + f[1 - (i & 1)][j][0]) % mod;
(up_sum[j][1] = up_sum[j - 1][1] + f[1 - (i & 1)][j][1]) % mod;
(up_sum[j][2] = up_sum[j - 1][2] + f[1 - (i & 1)][j][2]) % mod;
}
for (int j = 200; j >= 1; --j) {
(down_sum[j][0] = down_sum[j + 1][0] + f[1 - (i & 1)][j][0]) % mod;
(down_sum[j][1] = down_sum[j + 1][1] + f[1 - (i & 1)][j][1]) % mod;
(down_sum[j][2] = down_sum[j + 1][2] + f[1 - (i & 1)][j][2]) % mod;
}
for (int j = 1; j <= 200; ++j) {
f[i & 1][j][0] = (f[1 - (i & 1)][j][0] + f[1 - (i & 1)][j][1] + f[1 - (i & 1)][j][2]) % mod;
f[i & 1][j][1] = (down_sum[j + 1][0] + down_sum[j + 1][1]) % mod;
f[i & 1][j][2] = (up_sum[j - 1][0] + up_sum[j - 1][1] + up_sum[j - 1][2]) % mod;
}
} else {
for (int j = 1; j < a[i - 1]; ++j) {
f[i & 1][j][1] = (f[1 - (i & 1)][a[i - 1]][0] + f[1 - (i & 1)][a[i - 1]][1]) % mod;
}
f[i & 1][a[i - 1]][0] =
(f[1 - (i & 1)][a[i - 1]][0] + f[1 - (i & 1)][a[i - 1]][1] + f[1 - (i & 1)][a[i - 1]][2]) % mod;
for (int j = a[i - 1] + 1; j <= 200; ++j) {
f[i & 1][j][2] = (f[1 - (i & 1)][a[i - 1]][0] + f[1 - (i & 1)][a[i - 1]][1] +
f[1 - (i & 1)][a[i - 1]][2]) % mod;
}
}
} else {
if (a[i - 1] == -1) {
for (int j = 1; j < a[i]; ++j) {
f[i & 1][a[i]][2] += f[1 - (i & 1)][j][0] + f[1 - (i & 1)][j][1] + f[1 - (i & 1)][j][2];
f[i & 1][a[i]][2] %= mod;
}
f[i & 1][a[i]][0] = (f[1 - (i & 1)][a[i]][0] + f[1 - (i & 1)][a[i]][1] + f[1 - (i & 1)][a[i]][2]) % mod;
for (int j = a[i] + 1; j <= 200; ++j) {
f[i & 1][a[i]][1] += f[1 - (i & 1)][j][0] + f[1 - (i & 1)][j][1];
f[i & 1][a[i]][1] %= mod;
}
} else {
if (a[i] > a[i - 1]) {
f[i & 1][a[i]][2] =
(f[1 - (i & 1)][a[i - 1]][0] + f[1 - (i & 1)][a[i - 1]][1] + f[1 - (i & 1)][a[i - 1]][2]) %
mod;
} else if (a[i] == a[i - 1]) {
f[i & 1][a[i]][0] =
(f[1 - (i & 1)][a[i - 1]][0] + f[1 - (i & 1)][a[i - 1]][1] + f[1 - (i & 1)][a[i - 1]][2]) %
mod;
} else {
f[i & 1][a[i]][1] = (f[1 - (i & 1)][a[i - 1]][0] + f[1 - (i & 1)][a[i - 1]][1]) % mod;
}
}
}
}
ll ans = 0;
for (int i = 1; i <= 200; ++i) {
ans += f[n & 1][i][0] + f[n & 1][i][1];
ans %= mod;
}
cout << ans << endl;
return 0;
}