2019牛客暑期多校训练营(第六场)J Upgrading Technology 后缀和

 题意:有i个技能,每次升级都有花费cij,然后所有技能都达到j级送dj块钱,问你最多能赚多少

 解:先将花费乘-1转换为收益,对 a[i][j] 维护后缀和,表示 j+1~m 最大收益。

然后  j 从1 到 m 遍历,j 表示当前某个技能的最低等级,找到 第 i 个技能 最小的后缀和,减去这个后缀和并加上其他技能的后缀和,再加上所以技能都达到 j 的收益取最大值。 

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll sum[1005][1005];
int d[1005];
int a[1005][1005];
int main() {
	int cnt=1,t,n,m;
	scanf("%d",&t);
	while(t--) {
		scanf("%d %d",&n,&m);
		for(int i=1; i<=n; i++)
			for(int j=1; j<=m; j++)scanf("%d",&a[i][j]),a[i][j]=-a[i][j];
		for(int i=1; i<=m; i++)scanf("%d",&d[i]);
		
		for(int i=1;i<=n;i++){
			sum[i][m] = 0;
			for(int j=m-1;j>=0;j--){
				sum[i][j] = max(0ll,sum[i][j+1]+a[i][j+1]);
			}
		}
		ll now = 0,ans = 0;
		for(int j=0;j<=m;j++){
			for(int i=1;i<=n;i++)now+=a[i][j];
			now+=d[j];
			ll tp = 0,mi = 1e18;
			for(int i=1;i<=n;i++)tp+=sum[i][j],mi = min(mi,sum[i][j]);
			ans = max(ans,tp-mi+now);
		}
		printf("Case #%d: %lld\n",cnt++,ans);
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章