【每日一题】前缀和、滑动窗口

统计一个数前面的连续k个数和 premax
后面最大的连续k个数和 sufmax
最后遍历一遍,
ans=max(ans,preans+sufmax[i+1]);
ans=max(ans,preans+premax[i-k]);
【心得】
这里写复杂了=。= 还是代码写的太少
直接前缀和就可以 sum[i]-sum[i-k];sum[i+k-1]-sum[i-1]
我这里是用滑动窗口写的=====

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define LONGLONGMIN -922337203685477580
const int maxn = 2e5 + 10;

int nums[maxn];
int n, k;
ll premax[maxn];//以x结尾
ll sufmax[maxn];//以x开始

ll solve()
{
    ll preans = 0, sufans = 0;
    ll ans = 0;
    ll prevpre=LONGLONGMIN, prevsuf=LONGLONGMIN;
    int i;
    for (i = 0; i < k; ++i)
        preans += nums[i];
    for (i = n - 1; i >= n - k; --i)
        sufans += nums[i];
    premax[k-1]=preans; 
    sufmax[n-k]=sufans;

    for(int en=n-2;en>=k-1;en--){
        int st=en-k+1;
        sufans -= nums[en+1];
        sufans += nums[st];
        sufmax[st] = max(sufmax[st+1],sufans);
    }
    for(int st=1;st<=n-k;++st){
        int en = st+k-1;
        preans -= nums[st-1];
        preans += nums[en];
        premax[en]=max(premax[en-1],preans);
    }
    
    preans=premax[k-1];
    for(int i=k-1;i<n;++i){
        if(i==k-1) ans=max(ans,preans+sufmax[k]);
        else{
            preans -= nums[i-k];
            preans += nums[i];
            ans=max(ans,preans+sufmax[i+1]);
            ans=max(ans,preans+premax[i-k]);
        }
    }
    return ans;
}
int main(void)
{
    int T;
    cin >> T;
    while (T--) {       
        cin >> n >> k;
        ll sum=0;
        for (int i = 0; i < n; ++i) {
            cin >> nums[i];sum+=nums[i];
        }
        
        if (2 * k == n) {
            cout << sum << endl;
            continue;
        }

        for(int i = 0;i<=n;++i){
            premax[i]=sufmax[i]=LONGLONGMIN;
        }
        cout << solve() << endl;
    }

    return 0;
}
【简洁版本】
注意:
//处理前缀和题目,让nums数组下标从1开始更简单 此时[i,j]的和为sum[j]-sum[i-1]
//边界情况也更容易处理 [1,3]的和就是sum[3]-sum[0] sum初始化为0即可
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define LONGLONGMIN -922337203685477580
const int maxn = 2e5 + 10;

int nums[maxn];
int n, k;
ll premax[maxn];  // 以x结尾
ll sufmax[maxn];  // 以x开始
ll sum[maxn];

int main(void)
{
    int T;
    cin >> T;
    while (T--) {
        cin >> n >> k;
        //处理前缀和题目,让nums数组下标从1开始更简单 此时[i,j]的和为sum[j]-sum[i-1]
        //边界情况也更容易处理 [1,3]的和就是sum[3]-sum[0] sum初始化为0即可
        memset(sum, 0, sizeof(sum));
        for (int i = 1; i <= n; ++i) {
            cin >> nums[i];
            sum[i] += nums[i] + sum[i - 1];
        }

        if (2 * k == n) {
            cout << sum[n] << endl;
            continue;
        }
        memset(premax, -0x7f, sizeof(premax));
        memset(sufmax, -0x7f, sizeof(premax));
        for (int en = n; en >= k; en--) {
            int st = en - k + 1;
            sufmax[st] = max(sufmax[st + 1], sum[en] - sum[st-1]);
        }
        for (int st = 1; st <= n - k+1; ++st) {
            int en = st + k - 1;
            premax[en] = max(premax[en - 1], sum[en] - sum[st-1]);
        }
        ll ans=0;
        for (int en = k; en <= n; ++en) {
            ans = max(ans, sum[en]-sum[en-k] + sufmax[en + 1]);
            ans = max(ans, sum[en]-sum[en-k] + premax[en - k]);
            
        }
        cout<<ans<<endl;
    }

    return 0;
}




全部评论

相关推荐

把球:这个听过,你加了就会发现是字节的hr
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务