2020 CCPC-Wannafly Winter Camp Day6 ---I. 变大!
最后的答案一定是一段一段的,每段有一个最大值。
我们考虑将某一段全变成最大值需要的次数,每一次操作能将2个数变成最大值,所以一段长为L的全部变成最大值需要L/2次。
f[i][j]表示前i个数操作j次后的最大和。
考虑最后一段长度为k,则有(f[i][j] = MAX(f[i - k + 1][j - k / 2] + maxx * k))
#include <bits/stdc++.h>
using namespace std;
int f[55][55];
int a[55];
int main() {
int t;
scanf("%d" , &t);
while (t--) {
memset(f , 0 , sizeof(f));
int n;
scanf("%d" , &n);
for (int i = 1; i <= n; i++) scanf("%d" , &a[i]);
for (int i = 1; i <= n; i++){
int maxx = 0;
for (int j = i; j >= 1; j--) {
maxx = max(maxx , a[j]);
int p = (i - j + 1) / 2;
for (int k = p; k <= n; k++)
f[i][k] = max(f[i][k] , f[j - 1][k - p] + maxx * (i - j + 1));
}
}
for (int i = 1; i <= n; i++) printf("%d%s" , f[n][i] , i == n ? "
" : " ");
}
}