2024牛客暑期多校训练营6 I Intersecting Intervals

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

You are given a matrix A of n rows and m columns, containing only integers.

For each row i, choose a non-empty interval li​,ri​, such that the adjacent row's interval intersects, and maximize the sum of all integers over all intervals.

Formally, choose li​,ri​ such that 1≤li​≤ri​≤m, max(li​,li+1​)≤min(ri​,ri+1​) for all i∈Z∩[1,n), and maximize 

\sum_{i=1}^{n}\sum_{j=l_{i}}^{r_{i}}A_{i,j}

输入描述:

The first line contains one integer T (1≤T≤), representing the number of test cases.

For each test case, the first line contains two integers n,m (1≤n⋅m≤), representing the size of the matrix.

The following nnn lines, each contain mmm integers Ai,j (−≤Ai,j​≤), representing each element of the matrix.

It is guaranteed that ∑n⋅m≤106.

输出描述:

For each test case, output one line containing a single integer, representing the answer.

示例1

输入

5
4 4
-1 1 1 -1
1 1 -1 -1
-1 1 1 -1
-1 -1 1 1
3 4
2 -3 4 -1
1 2 -4 -7
1 1 -7 2
4 3
1 -1 1
-2 4 5
2 -3 2
6 -5 7
1 1
1
2 2
-1 -1
-1 -2

输出

8
8
20
1
-2

思路:每行用一个pre数组来记录 pre[ j ] = max ( { pre [ j - 1 ] + a [ j ] , 0 , a [ j ] } ),用一个next数组来记录 next [ j ] = max ( { next [ j + 1 ] + a [ j ] , 0 , a [ j ] } ),用数组 v 来更新 dp 数组 ,然后将数组 v 赋值给 dp 数组,最后输出 dp 数组中的 最大值。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
signed main()
{
	IOS
	int t;
	cin >> t;
	while(t--){
		int n,m;
		cin >> n >> m;
		vector<int> dp(m+1);
		for(int i=1;i<=n;i++){
			vector<int> a(m+1),v(m+1,-1e18),pre(m+1),next(m+2);
			for(int j=1;j<=m;j++){
				cin >> a[j];
				pre[j]=max({pre[j-1]+a[j],(int)0,a[j]});//记录当前这个下标的最大值(从前往后推) 
			}
			for(int j=m;j>=1;j--){
				next[j]=max({next[j+1]+a[j],(int)0,a[j]});//记录当前这个下标的最大值(从后往前推) 
			}
			int maxn=-1e18;
			for(int j=1;j<=m;j++){//从前往后记录maxn和数组v的最大值
				maxn=max(maxn+a[j],pre[j-1]+a[j]+dp[j]);
				v[j]=max(v[j],maxn+next[j+1]); 
			}
			maxn=-1e18;
			for(int j=m;j>=1;j--){//从后往前记录maxn和数组v的最大值
				maxn=max(maxn+a[j],next[j+1]+a[j]+dp[j]);
				v[j]=max(v[j],maxn+pre[j-1]); 
			}
			dp.swap(v);//更新dp数组 
		}
		cout << *max_element(dp.begin(),dp.end()) << endl;//取dp数组中的最大值 
	}
	return 0;
}

  • 14
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值