網上搜不到題解…搞了兩天才勉強跑過去…太弱…
做法應該就是區間dp吧, 把所有詢問的 c 值排序, 由大到小枚舉每一個 c ,令 f[i][j]表示當前的區間 [i, j] 中能取到的最大值, 然後用一種神乎其神的方法狀態轉移和記錄答案…具體可以看代碼.
AC code :
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
inline void read(int &x){x=0;char c;while((c=getchar())<'0'||c>'9');for(x=c-'0';(c=getchar())>='0'&&c<='9';x=x*10+c-'0');}
const int N = 51, M = 5001 ;
struct Query
{
int l, r, m;
}q[M];
int f[N][N], g[M][N][N];
int T[M], n, m, c;
struct Data
{
Data *ch[2];
int p, k;
}P[N * (N + 1) * M / 2], *head[N][N], *cur = P;
inline void insert(int l, int r, int d, int k)
{
cur->ch[0] = head[l][d - 1], cur->ch[1] = head[d + 1][r];
cur->p = d, cur->k = k, head[l][r] = cur++;
}
void dfs(Data *o, int l, int r)
{
int d = o->p;
if (l < d) dfs(o->ch[0], l, d - 1);
printf("%d ", T[o->k]);;
if (d < r) dfs(o->ch[1], d + 1, r);
}
int main()
{
freopen("in.txt", "r", stdin);
read(n), read(m);
for (int i = 1; i <= m; ++i)
read(q[i].l), read(q[i].r), read(q[i].m), T[i] = q[i].m;
sort(T + 1, T + m + 1);
c = unique(T + 1, T + m + 1) - T - 1;
for (int i = 1; i <= m; ++i)
{
q[i].m = lower_bound(T + 1, T + c + 1, q[i].m) - T;
int l = q[i].l, r = q[i].r;
for (int k = 1; k <= q[i].m; ++k) g[k][l][r] += T[k];
}
for (int k = 1; k <= c; ++k) for (int l = n; l; --l) for (int r = l; r <= n; ++r)
g[k][l][r] += g[k][l + 1][r] + g[k][l][r - 1] - g[k][l + 1][r - 1];
for (int i = 1; i <= n; ++i) for (int j = i; j <= n; ++j) f[i][j] = -1;
for (int k = c; k; --k)
{
for (int l = 0; l < n; ++l) for (int i = 1; i + l <= n; ++i)
{
int j = i + l, ret = 0, p = i;
for (int d = i; d <= j; ++d)
{
int tmp = f[i][d - 1] + f[d + 1][j] + g[k][i][j] - g[k][i][d - 1] - g[k][d + 1][j];
if (ret < tmp) ret = tmp, p = d;
}
if (f[i][j] < ret) f[i][j] = ret, insert(i, j, p, k);
}
}
printf("%d\n", f[1][n]);
dfs(head[1][n], 1, n);
putchar('\n');
return 0;
}
[ 大家好,窩是一個來自超級大弱省甘肅的沙茶,第一次寫博客覺得好新鮮呢(=゚ω゚)ノ,歡迎OIer們加QQ交流:745350128 QAQ