1067A Array Without Local Maximums
阿新 • • 發佈:2019-01-23
題意:給你一個序列,序列中的-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]有關,這樣第一維可以用滾動陣列優化掉。
更新f[i]的時候需要分類討論,其中,a[i]=a[i-1]=-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; 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; }