c++程序最大区间和解析

描述

输入 n 个整数,在所有连续且长度为K的区间中,找到最大的区间和。

输入描述

第一行包括两个整数 n 和 K。
第二行包括 n 个整数。

输出描述

输出两行。第一行一个整数,表示最大区间和。
第二行两个整数,表示最大区间和的起点下标和终点下标。

答案

#include<bits/stdc++.h>
using namespace std;
int a[5000001]={};
int s[5000001]={};
int main(){
	int n,K;
	cin>>n>>K;
	for(int i=1;i<=n;i++){
		//TODO
		cin>>a[i];
	}
	s[1]=a[1];
	for(int i=2;i<=n;i++){
		//TODO
		s[i]=s[i-1]+a[i];
	}	
	int res=0;
	int b,e;
	for(int i=K;i<=n;i++){
		//TODO
		int t=s[i]-s[i-K];
		if(t>res){
			//TODO
			res=t;
			b=i-K+1;
			e=i;
		}
		
	}
	cout << res << endl;
	cout << b << " " << e << endl;
	return 0;
}

答案解析

1. 头文件包含和命名空间声明

#include<bits/stdc++.h>
using namespace std;

  • #include<bits/stdc++.h>:这是一个非标准但被广泛使用的头文件,它实际上包含了 C++ 中大多数常用的标准库头文件(如<iostream><vector><algorithm>等),方便在编写代码时可以直接使用各种标准库提供的功能,而不用逐个去包含对应的具体头文件。不过在一些严格的编译环境或者竞赛规则中,可能不允许使用这个头文件,更推荐按照实际需求分别包含具体的标准库头文件。
  • using namespace std;:声明使用std命名空间。C++ 标准库中的类、函数、对象等大多定义在std命名空间下,通过这行声明,后续代码中使用标准库的相关内容时就可以省略std::前缀,使代码书写更简洁,但也存在一定的命名冲突风险(如果自定义的名称和std里的重名了)。

2. 全局数组定义

int a[5000001]={};
int s[5000001]={};

这里定义了两个整型数组as,数组大小都为5000001,并且都进行了初始化,将所有元素初始化为0。通常这样大的数组在程序中可能用于存储较多的数据,比如a数组可能用于存放输入的一系列数值,s数组往往用于存储某种前缀和相关的数据(从后续代码逻辑来看是这样的用途)。

3. main函数部分

  • 输入数据部分

int n,K;
cin>>n>>K;
for(int i=1;i<=n;i++){
    //TODO
    cin>>a[i];
}

  • 首先定义了两个整型变量nKn大概率用于表示后续要输入的数据个数,K可能是一个用于控制计算范围或者窗口大小之类的参数(从后面代码逻辑推断)。

  • 然后通过cin从标准输入读取用户输入的nK的值。

  • 接着使用for循环,循环n次,每次从标准输入读取一个整数并存入a数组中,这样就将一系列的输入数据存储到了a数组中。

  • 计算前缀和部分

s[1]=a[1];
for(int i=2;i<=n;i++){
    //TODO
    s[i]=s[i-1]+a[i];
}

这段代码用于计算数组a的前缀和并存储到数组s中。具体来说,首先将s[1]初始化为a[1],然后从i = 2开始循环到n,对于每个is[i]的值等于前一个位置的前缀和s[i - 1]加上当前位置a数组中的元素a[i],这样经过循环后,s数组中就存储了对应位置的前缀和信息,例如s[3]就表示a[1] + a[2] + a[3]的和。

  • 寻找最大子段和(滑动窗口方式)部分

int res=0;
int b,e;
for(int i=K;i<=n;i++){
    //TODO
    int t=s[i]-s[i-K];
    if(t>res){
        //TODO
        res=t;
        b=i-K+1;
        e=i;
    }
}

  • 首先定义了三个变量,res用于存储找到的最大子段和,初始化为0be可能用于记录最大子段和对应的区间的起始和结束位置(从后面代码看确实如此)。

  • 然后有一个for循环,从i = K开始到n结束,这里的K就是前面输入的那个参数,循环的目的是以长度为K的滑动窗口去遍历数组(基于前缀和来操作)。在每次循环中:

    • 计算当前窗口内的子段和,通过s[i] - s[i - K]来得到,即当前位置的前缀和减去窗口起始位置前一个位置的前缀和,这样就得到了长度为K的窗口内元素的和,存储在变量t中。
    • 接着判断这个和t是否大于当前记录的最大子段和res,如果大于,就更新rest,同时更新b为当前窗口的起始位置(即i - K + 1),e为当前窗口的结束位置(即i)。
  • 输出结果部分

cout << res << endl;
cout << b << " " << e << endl;

最后,将找到的最大子段和res输出到标准输出,然后输出对应的最大子段和区间的起始位置b和结束位置e,中间用空格隔开,方便查看最终的计算结果。

总的来说,这段代码的功能大致是输入一组数据,先计算其前缀和,然后通过滑动窗口的方式,利用前缀和去寻找长度为K的子段中的最大和,并输出最大和以及对应的子段区间。 不过需要注意的是,代码中有些地方写了//TODO注释,可能意味着这些地方后续还有完善或者添加其他逻辑的需求,当前代码只是实现了核心的上述功能。另外,在实际使用中,要确保输入的数据合法性以及考虑数组大小是否可能会导致栈溢出等问题(毕竟定义了较大的数组)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值