链接:https://ac.nowcoder.com/acm/contest/918/J
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
在Farmer John最喜欢的节日里,他想要给他的朋友们赠送一些礼物。由于他并不擅长包装礼物,他想要获得他的奶牛们的帮助。你可能能够想到,奶牛们本身也不是很擅长包装礼物,而Farmer John即将得到这一教训。
Farmer John的N头奶牛(1≤N≤10^4)排成一行,方便起见依次编号为1…N。奶牛i的包装礼物的技能水平为si。她们的技能水平可能参差不齐,所以FJ决定把她的奶牛们分成小组。每一组可以包含任意不超过K头的连续的奶牛(1≤K≤10^3),并且一头奶牛不能属于多于一个小组。由于奶牛们会互相学习,这一组中每一头奶牛的技能水平会变成这一组中水平最高的奶牛的技能水平。
请帮助FJ求出,在他合理地安排分组的情况下,可以达到的技能水平之和的最大值。
输入描述:
输入的第一行包含N和K。以下N行按照N头奶牛的排列顺序依次给出她们的技能水平。技能水平是一个不超过10^5的正整数。
输出描述:
输出FJ通过将连续的奶牛进行分组可以达到的最大技能水平和。
示例1
输入
7 3 1 15 7 9 2 5 10
输出
84
说明
在这个例子中,最优的方案是将前三头奶牛和后三头奶牛分别分为一组,中间的奶牛单独成为一组(注意一组的奶牛数量可以小于K)。这样能够有效地将7头奶牛的技能水平提高至15、15、15、9、10、10、10,和为84。
这题是搜的题解,不太会,
https://www.cnblogs.com/YDDDD/p/10997104.html
每次枚举当前的i点时,用j去枚举之前的点,由于不可重复分组所以要类似01背包的倒序枚举,假设我要把j到i分成一组,那么就是dp[j-1]+(i-j+1)*这个区间的最大值
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e4+10; int f[N],a[N]; int n,k; int F_Max[N][20]; void Init() { for(int i = 1; i <= n; i++) F_Max[i][0] = a[i]; for(int i = 1; (1<<i) <= n; i++) for(int j = 1; j+(1<<i)-1<= n; j++) F_Max[j][i] = max(F_Max[j][i-1],F_Max[j+(1<<(i-1))][i-1]); } int Query_max(int l,int r) { int k = (int)(log(double(r-l+1))/log((double)2)); return max(F_Max[l][k], F_Max[r-(1<<k)+1][k]); } int main() { cin>>n>>k; for(int i=1;i<=n;++i) scanf("%d",&a[i]); for (int i=1;i<=n;i++) { int mx=0; for (int j=i;j>=1&&j>i-k;j--) { mx=max(mx,a[j]); f[i] = max(f[i], f[j - 1] + mx * (i - j + 1)); } } printf("%d\n",f[n]); }
文章来源: https://blog.csdn.net/qq_41286356/article/details/92639288