[GESP202503 六级] 环线(含视频)

视频讲解:GESP202503 六级 环线-信息学奥赛GESP等级考试真题解析

一、原题

题目描述

小 A 喜欢坐地铁。地铁环线有 n 个车站,依次以 1,2,⋯,n 标号。车站 i (1≤i<n) 的下一个车站是车站 i+1。特殊地,车站 n 的下一个车站是车站 1。

小 A 会从某个车站出发,乘坐地铁环线到某个车站结束行程,这意味着小 A 至少会经过一个车站。小 A 不会经过一个车站多次。当小 A 乘坐地铁环线经过车站 i 时,小 A 会获得 ai​ 点快乐值。请你安排小 A 的行程,选择出发车站与结束车站,使得获得的快乐值总和最大。

输入格式

第一行,一个正整数 n,表示车站的数量。

第二行,n 个整数 ai​,分别表示经过每个车站时获得的快乐值。

输出格式

一行,一个整数,表示小 A 能获得的最大快乐值。

输入输出样例

输入 #1

复制代码
4
-1 2 3 0

输出 #1

复制代码
5

输入 #2

复制代码
5
-3 4 -5 1 3

输出 #2

复制代码
5

说明/提示

对于 20% 的测试点,保证 1≤n≤200。

对于 40% 的测试点,保证 1≤n≤2000。

对于所有测试点,保证 1≤n≤2×10^5,−10^9≤ai​≤10^9。

二、做题思路

1)填充数据

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int m=200005;
long long a[m];
int main(){
	//1)填充数据
	//1.1)确定车站数量n
	int n;cin>>n; 
	//1.2)填充n个车站的快乐值
	for(int i=1;i<=n;i++) cin>>a[i];
	return 0;
} 

2)动态规划:求最大/小子段和

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int m=200005;
long long a[m];
long long max_dp[m],min_dp[m];
long long max_sum,min_sum;
int main(){
	//1)填充数据
	//... 
	//2)动态规划:求最大/小子段和
	//2.1)初始化dp
	max_sum=min_sum=max_dp[1]=min_dp[1]=a[1];
	//2.2)计算当前最优=最优(累加之前,不累加之前) 
	for(int i=2;i<=n;i++){
		//计算当前最优 
		max_dp[i]=max(a[i]+max_dp[i-1],a[i]);
		min_dp[i]=min(a[i]+min_dp[i-1],a[i]);
		//比较找出所有最优中的最优 
		max_sum=max(max_dp[i],max_sum);
		min_sum=min(min_dp[i],min_sum);
	}
	return 0;
} 

3)计算总和 和 最大值

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int m=200005;
long long a[m];
long long max_dp[m],min_dp[m];
long long max_sum,min_sum;
int main(){
	//1)填充数据
	//... 
	//2)动态规划:求最大/小子段和
	//2.1)初始化dp
	long long maxx=a[1],sum=a[1];
	max_sum=min_sum=max_dp[1]=min_dp[1]=a[1];
	//2.2)计算当前最优=最优(累加之前,不累加之前) 
	for(int i=2;i<=n;i++){
		//计算当前最优 
		max_dp[i]=max(a[i]+max_dp[i-1],a[i]);
		min_dp[i]=min(a[i]+min_dp[i-1],a[i]);
		//比较找出所有最优中的最优 
		max_sum=max(max_dp[i],max_sum);
		min_sum=min(min_dp[i],min_sum);
		//3)计算总和 和 最大值
		sum+=a[i];
		maxx=max(maxx,a[i]);
	}
	return 0;
} 

4)输出结果

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int m=200005;
long long a[m];
long long max_dp[m],min_dp[m];
long long max_sum,min_sum;
int main(){
	//1)填充数据
	//... 
	//2)动态规划:求最大/小子段和
	//....
		//3)计算总和 和 最大值
		//...
	//4)输出结果
	//4.1)全是负数 ,输出最大值
	if(maxx<0) cout<<maxx;
	//4.2)否输输出最优 max(最大子段和,总和-最小子段和)
	else{
		cout<<max(max_sum,sum-min_sum);
	}
	return 0;
} 

三、答案

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int m=200005;
long long a[m];
long long max_dp[m],min_dp[m];
long long max_sum,min_sum;
int main(){
	//1)填充数据
	//1.1)确定车站数量n
	int n;cin>>n; 
	//1.2)填充n个车站的快乐值
	for(int i=1;i<=n;i++) cin>>a[i];
	//2)动态规划:求最大/小子段和
	//2.1)初始化dp
	long long maxx=a[1],sum=a[1];
	max_sum=min_sum=max_dp[1]=min_dp[1]=a[1];
	//2.2)计算当前最优=最优(累加之前,不累加之前) 
	for(int i=2;i<=n;i++){
		//计算当前最优 
		max_dp[i]=max(a[i]+max_dp[i-1],a[i]);
		min_dp[i]=min(a[i]+min_dp[i-1],a[i]);
		//比较找出所有最优中的最优 
		max_sum=max(max_dp[i],max_sum);
		min_sum=min(min_dp[i],min_sum);
		//3)计算总和 和 最大值
		sum+=a[i];
		maxx=max(maxx,a[i]);
	}
	//4)输出结果
	//4.1)全是负数 ,输出最大值
	if(maxx<0) cout<<maxx;
	//4.2)否输输出最优 max(最大子段和,总和-最小子段和)
	else{
		cout<<max(max_sum,sum-min_sum);
	}
	
	return 0;
} 
相关推荐
w_zero_one1 小时前
递归算法(一)
java·开发语言·算法
风影同志783243 小时前
20 个比特能装下多少行情?——实测拆解 Kronos 的 K 线分词器
算法
写的都是BUG3 小时前
APK 里的钥匙,一直就放在门口:聊聊加固真正该做什么
前端·算法
地平线开发者4 小时前
CLIP 的零样本分类:一组文本如何变成图像分类器?
算法
京东云开发者4 小时前
从“会生成”到“能生产”:萤火虫 AIGC 平台的 AI Infra 实践
算法·aigc·产品
youshi66684 小时前
PID——算法改进
算法
一只不想敲代码的程序猿6 小时前
如何更高效地拆解问题?
算法
微尘hjx7 小时前
【Deep-OC-SORT 02】多轨迹算法Deep-OC-SORT-相对 OC-SORT 的改进点
人工智能·算法·yolo·目标跟踪·视觉检测·ultralytics·deep-oc-sort
梦帮科技7 小时前
意识启发式量子隧穿退火算法用于全局优化 (CITA) 完整技术指南
网络·人工智能·算法·量子计算·模拟退火算法
一去不复返的通信er8 小时前
排序 + 双指针:力扣15三数之和
算法·leetcode