Codeforces 1178F2 Long Colorful Strip 区间dp (看题解)

Long Colorful Strip

感觉还是一个比较难的区间dp

贴个官方题解

#include<bits/stdc++.h>
using namespace std;

const int N = 1007;
const int mod = 998244353;

inline void add(int &a, int b) {
    a += b; if(a >= mod) a -= mod;
}

int n, m;
int dp[N][N];
vector<int> a;
vector<int> V[N];

int dfs(int i, int j) {
    if(i > j) return 1;
    int &ans = dp[i][j];
    if(~ans) return ans;
    ans = 0;
    int mn = n + 1;
    for(int k = i; k <= j; k++) {
        mn = min(mn, a[k]);
    }
    int u = V[mn][0];
    int v = V[mn].back();
    if(u < i || v > j) return ans = 0;
    int l_ret = 0;
    int r_ret = 0;
    for(int k = i; k <= u; k++) {
        add(l_ret, 1LL * dfs(i, k - 1) * dfs(k, u - 1) % mod);
    }
    for(int k = v; k <= j; k++) {
        add(r_ret, 1LL * dfs(v + 1, k) * dfs(k + 1, j) % mod);
    }
    ans = 1LL * l_ret * r_ret % mod;
    for(int i = 0; i < (int)V[mn].size() - 1; i++) {
        ans = 1LL * ans * dfs(V[mn][i] + 1, V[mn][i + 1] - 1) % mod;
    }
    return ans;
}

int main() {
    memset(dp, -1, sizeof(dp));
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; i++) {
        int x; scanf("%d", &x);
        if(a.empty() || a.back() != x) {
            a.push_back(x);
        }
    }
    if(a.size() > n * 2) return puts("0"), 0;
    for(int i = 0; i < (int)a.size(); i++) V[a[i]].push_back(i);
    printf("%d
", dfs(0, (int)a.size() - 1));
    return 0;
}

/*
*/