暴力思路
题目要我们找两个不重叠的区间,并使区间的值最大。那我们可以考虑使用双重循环搭配前缀和暴力求最大值。代码如下。
for(int i=1;i<=n;i++)
{
ll l=sum[i+k-1]-sum[i-1],maxx;
for(int j=i+k;j<=n;j++)
{
maxx=l+sum[j+k-1]-sum[j-1];
if(maxx>ans.sum)
{
ans.x=i;
ans.y=j;
ans.sum=maxx;
}
}
}
但是暴力的时间复杂度是一定会超时的。那我们考虑一下优化。
优化思路
我们可以思考一下如何把第二层循环给优化掉。我们可以用一个结构体数组 m a x x [ i ] maxx[i] maxx[i] 来记录 i ∼ n i \sim n i∼n 的最大的区间值,并记录这个区间的起点。这样我们就把第二层循环给优化掉了。
最重要的注意数据范围,要开 long long
。
代码
#include<bits/stdc++.h>
#include<cstring>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#include<map>
#define ll unsigned long long
#define lhs printf("\n");
using namespace std;
const int N=3e5+10;
const int M=2024;
const int inf=0x3f3f3f3f;
ll n,k;
ll a[N];
ll sum[N];
struct node
{
ll num;
int id;
}maxx[N];
struct nodee
{
ll sum;
ll x,y;
}ans;
int main()
{
scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
sum[i]=sum[i-1]+a[i];//前缀和
}
for(int i=n;i>=1;i--)
{
if(i+k-1>n)continue;
ll l=sum[i+k-1]-sum[i-1];
//更新最大值
if(maxx[i+1].num>l)
{
maxx[i].num=maxx[i+1].num;
maxx[i].id=maxx[i+1].id;
}
else
{
maxx[i].num=l;
maxx[i].id=i;
}
}
for(int i=1;i<=n;i++)
{
if(i+k-1>n)continue;
ll l=sum[i+k-1]-sum[i-1];
ll r=maxx[i+k].num,rid=maxx[i+k].id;
if(l+r>ans.sum)
{
ans.x=i;
ans.y=rid;
ans.sum=r+l;
}
}
printf("%lld %lld",ans.x,ans.y);
return 0;
}