#区间dp,离散#D 弱者对决

题目


分析

(dp[i][j][x])表示当前区间为([i,j]),最小值为(x)的最大总分,
状态转移方程可以用后缀最大值优化到(O(n^3m)),主要难点是输出方案
后缀最大值需要记录是在哪个位置取得最大值


代码

#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
using namespace std;
const int N = 4011, M = 61;
int n, m, tot, c[N], a[N], b[N], L[N], R[N];
int dp[M][M][N], f[M][M][N], p[M][M][N], pf[M][M][N];
inline signed iut() {
    rr int ans = 0;
    rr char c = getchar();
    while (!isdigit(c)) c = getchar();
    while (isdigit(c)) ans = (ans << 3) + (ans << 1) + (c ^ 48), c = getchar();
    return ans;
}
inline void print(int ans) {
    if (ans > 9)
        print(ans / 10);
    putchar(ans % 10 + 48);
}
inline void calc(int l, int mid, int r) {
    for (rr int i = 1; i <= tot; ++i) c[i] = 0;
    for (rr int i = 1; i <= m; ++i)
        if (l <= L[i] && L[i] <= mid && mid <= R[i] && R[i] <= r)
            ++c[a[i]];
}
inline void dfs(int l, int r, int now) {
    rr int mid = p[l][r][now];
    if (l < mid)
        dfs(l, mid - 1, pf[l][mid - 1][now]);
    printf("%d ", b[now]);
    if (mid < r)
        dfs(mid + 1, r, pf[mid + 1][r][now]);
}
signed main() {
    freopen("baddream.in", "r", stdin);
    freopen("baddream.out", "w", stdout);
    n = iut(), m = iut();
    for (rr int i = 1; i <= m; ++i) L[i] = iut(), R[i] = iut(), b[i] = a[i] = iut();
    sort(b + 1, b + 1 + m), tot = unique(b + 1, b + 1 + m) - b - 1;
    for (rr int i = 1; i <= m; ++i) a[i] = lower_bound(b + 1, b + 1 + tot, a[i]) - b;
    for (rr int i = n; i >= 1; --i)
        for (rr int j = i; j <= n; ++j) {
            for (rr int k = i; k <= j; ++k) {
                calc(i, k, j);
                for (rr int o = tot, sum = 0; o; --o) {
                    sum += c[o];
                    rr int now = dp[i][k - 1][o] + dp[k + 1][j][o] + sum * b[o];
                    if (now >= f[i][j][o])
                        f[i][j][o] = now, p[i][j][o] = k;
                }
            }
            for (rr int o = tot; o; --o)
                if (f[i][j][o] >= dp[i][j][o + 1])
                    dp[i][j][o] = f[i][j][o], pf[i][j][o] = o;
                else
                    dp[i][j][o] = dp[i][j][o + 1], pf[i][j][o] = pf[i][j][o + 1];
        }
    printf("%d
", dp[1][n][1]);
    dfs(1, n, pf[1][n][1]);
    return 0;
}
原文地址:https://www.cnblogs.com/Spare-No-Effort/p/14074913.html