https://www.acwing.com/problem/content/137/
The common way is to find the sum of prefixes. The maximum value of sum[i]-sum[j] is to enumerate each sum[i], that is, the right endpoint. For each number, find the left endpoint of the largest sum[j], and then find the maximum value.
In the process, it can be optimized. For each right endpoint, it is unnecessary to traverse all its left endpoints to find the minimum value. We can maintain a monotonically increasing sequence from left to right, and directly determine that the minimum value of the left endpoint is the leftmost value of the sequence.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=3e5+10;
int q[maxn];
ll sum[maxn];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
{
ll t;
scanf("%lld",&t);
sum[i]=sum[i-1]+t;
}
int head=1;
int tail=0;
ll maxx=-1e18;
for(int i=1; i<=n; i++)
{
while((i-q[head])>m)
{
head++;
}
maxx=max(maxx,sum[i]-sum[q[head]]);
while(head<=tail&&sum[i]<sum[q[tail]])
{
tail--;
}
q[++tail]=i;
}
printf("%lld",maxx);
}
I wrote it backwards to understand the meaning better.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=3e5+10;
int q[maxn];
ll sum[maxn];
int main()
{
int n,m;
scanf("%d%d",&n,&m); // 0~n
for(int i=1; i<=n; i++)
{
ll t;
scanf("%lld",&t);
sum[i]=sum[i-1]+t;
}
int head=1;
int tail=0;
ll maxx=-1e18;
q[head]=n;
for(int i=n; i>=0; i--)
{
while((q[head]-i)>m)
{
head++;
}
maxx=max(maxx,sum[q[head]]-sum[i]);
while(sum[i]>sum[q[tail]]&&head<=tail)
{
tail--;
}
q[++tail]=i;
}
printf("%lld",maxx);
}