CF2021D Boss, Thirsty 题解

先考虑一个朴素的 dp,设 dpi,l,r 表示在第 i 行取了第 l 列到第 r 列之间的饮料的最大利润。

sumi,j 表示 k=1jai,k,有转移 dpi,l,r=max(dpi1,L,R+sumrsuml1) 其中 L,R 满足 l<LrlR<r

直接转移复杂度直接起飞,考虑优化。可以发现,上面 dp 的转移 L,R 的限制只需要满足其一即可。于是设 dpLi,l 表示在第 i 行固定左端点为 l 而右端点随便的最大利润,同理定义 dpRi,r 为在第 i 行固定右端点为 r 而左端点随便的最大利润。

先考虑 dpR 的转移:

dpRi,r=sumi,r+max{maxk=1i(dpLi1,kminp=1k1sumi,p),maxk=1i1(dpRi1,kminp=1ksumi,p)}

转移时通过记录前缀最小值和最大值来转移。

dpL 的转移时同理的,可以通过维护后缀最大值来优化。

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll inf = 0x3f3f3f3f3f3f3f3f;
int n, m;
int turn(int x, int y) {return x * (m + 1) + y;}
ll a[400005], sum[400005], dpL[400005], dpR[400005];
void solve() {
	ll ans = -inf;
	scanf("%d %d", &n, &m);
	for(int i = 1; i <= n; i++) {
		sum[turn(i, 0)] = 0;
		for(int j = 1; j <= m; j++) scanf("%lld", &a[turn(i, j)]), sum[turn(i, j)] = sum[turn(i, j - 1)] + a[turn(i, j)];
	}
	ll minn = inf; for(int i = 1; i <= m; i++) minn = min(minn, sum[turn(1, i - 1)]), dpR[turn(1, i)] = sum[turn(1, i)] - minn;
	minn = -inf; for(int i = m; i >= 1; i--) minn = max(minn, sum[turn(1, i)]), dpL[turn(1, i)] = minn - sum[turn(1, i - 1)];
	for(int i = 2; i <= n; i++) {
		ll minn = inf, tot = -inf; for(int j = 1; j <= m; j++) {
			tot = max(tot, dpL[turn(i - 1, j)] - minn);
			dpR[turn(i, j)] = tot + sum[turn(i, j)];
			minn = min(minn, sum[turn(i, j - 1)]);
			tot = max(tot, dpR[turn(i - 1, j)] - minn); 
		}
		minn = -inf, tot = -inf; for(int j = m; j >= 1; j--) {
			tot = max(tot, dpR[turn(i - 1, j)] + minn);
			dpL[turn(i, j)] = tot - sum[turn(i, j - 1)];
			minn = max(minn, sum[turn(i, j)]);
			tot = max(tot, dpL[turn(i - 1, j)] + minn); 
		}
	}
	for(int j = 1; j <= m; j++) ans = max(ans, max(dpL[turn(n, j)], dpR[turn(n, j)]));
	printf("%lld\n", ans);
}
int main() {
	int t; cin>>t;
	while(t--) solve(); 
	return 0;
}
posted @   ddxrS  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示