像所有其他程序员一样,Sergey 非常喜欢喝咖啡,于是他每天喝恰好 K 杯咖啡。
Sergey 的一天被分成 N 段。对于每段时间,他知道自己可以写多少 KB 代码。
对于每段时间,Sergey 可以选择是否喝一杯咖啡。如果他在某段时间喝了一杯咖啡,则
他在该段时间不写任何代码,但他可以获得状态加成——如果他在某段时间选择不喝咖啡,
而上一次喝咖啡的时间距离现在不超过 D 段,则在该段时间内他可以写出正常情况下 M 倍
的代码。
作为他的生产力顾问(你的新职位!),请帮助 Sergey 规划他一天喝咖啡的时间,使他在
喝了恰好 K 杯咖啡的前提下写出最多的代码。
输入格式
输入数据第一行包含一个整数 T ,表示数据组数。接下来是 T 组数据。
每组数据第一行包含四个整数 N; K; D 和 M 。
接下来的一行包含 N 个整数 A1; A
2; : : : ; A
N ,表示 Sergey 每段时间写代码的 KB 数。
输出格式
对于每组数据,输出 Sergey 在喝了恰好 K 杯咖啡的前提下写出最多的代码的 KB 数。
数据范围
• 1 M; Ai 1000
样例数据
输入
1
5 2 2 10
1 2 3 4 5
输出
110
样例解释
第一组样例,Sergey 在第 1 段和第 3 段喝咖啡。在这两段时间里他不写任何代码,但在
其余的时间里他的写的代码量将乘 10,故总的代码量为 (2 + 4 + 5) 10 = 110KB。
https://www.codechef.com/LTIME28/problems/COFFEE
#include <bits/stdc++.h> #define pb push_back #define sqr(x) (x)*(x) #define sz(a) int(a.size()) #define reset(a,b) memset(a,b,sizeof(a)) #define oo 1000000007 using namespace std; typedef pair<int,int> pii; typedef long long ll; const int maxn=5007; int n,m,k,d,a[maxn]; ll dp[maxn][maxn],s[maxn]; int myq[maxn]; int main(){ // freopen("input.txt","r",stdin); int T; scanf("%d",&T); while(T--){ scanf("%d%d%d%d",&n,&k,&d,&m); for(int i=1; i<=n; ++i){ scanf("%d",&a[i]); s[i]=s[i-1]+a[i]; dp[0][i]=s[i]; } for(int i=1; i<=k; ++i){ int first=1, last=0; for(int p=i; p<=n; ++p){ while(first<=last && p-myq[first]>d) ++first; while(first<=last && dp[i-1][myq[last]-1] - s[myq[last]]*m <= dp[i-1][p-1] - s[p]*m) --last; myq[++last]=p; dp[i][p] = (s[p] - s[myq[first]])*m + dp[i-1][myq[first]-1]; if(p>i) dp[i][p] = max(dp[i][p], a[p] + dp[i][p-1]); } } printf("%lld\n",dp[k][n]); } }