码迷,mamicode.com
首页 > 其他好文 > 详细

D. Yet Another Subarray Problem 思维 难

时间:2019-07-23 11:19:13      阅读:119      评论:0      收藏:0      [点我收藏+]

标签:ons   iostream   gif   subarray   std   sum   tar   force   The   

D. Yet Another Subarray Problem

这个题目很难,我比赛没有想出来,赛后又看了很久别人的代码才理解。

这个题目他们差不多是用一个滑动窗口同时枚举左端点和右端点,具体如下:

首先枚举0~m,这个是说更新的位置,如果是1 当m==3 就更新1 4 7 10...

如果是2,当m==3 就更新 2 6 8 11....

最后都会被更新的。

核心代码

 for (int j = 0; j < n - i; ++j) {
     s += sum[j];
     if (j % m == 0) s -= k;//这个在判断是不是经过了一个区间,如果经过了就-k
     ans = max(ans, s - MIN);//这个是在判断这个时候枚举的区间左端点和区间右端点是不是可以更新答案
     if (j % m == m - 1) MIN = min(MIN, s);//这个就是在更新区间左端点,只有特定的时刻才可以更新,
    //只有在区间左端点才可以,因为我要更新的是下一个区间的右端点,如果提前更新了,那么就会被提前用,可能更新不该更新的东西。
    //左端点是由s来更新的,所以不需要考虑k的问题,
    //这个左端点只有特定时候才可以更新,因为我们枚举了每一个区间为m的起点,意思就是说我们确定了每一个区间
    //当j%m==m-1就是说到了区间的右端点,只有这个时候才可以更新,因为这个时候和我们想更新的是下一个区间的右端点,
    //所以这个才满足两点之间相隔了若干个k,这样子就可以一 前缀相减+k的个数相减*k。
 }

 

技术图片
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
const int maxn = 3e5 + 10;
typedef long long ll;
ll n, m, ans, k, a[maxn], sum[maxn];

int main()
{
    ans = 0;
    scanf("%lld%lld%lld", &n, &m, &k);
    for (int i = 0; i < n; i++) scanf("%lld", &a[i]);
    for(int i=0;i<m;i++)//枚举第一个区间的起点
    {
        for (int j = i; j < n; j++) sum[j - i] = a[j];
        ll mins = 0, s = 0;
        for(int j=0;j<n-i;j++)
        {
            s += sum[j];
            if (j%m == 0) s -= k;
            ans = max(ans, s - mins);
            if (j%m == m - 1) mins = min(mins, s);
        }
    }
    printf("%lld\n", ans);
}
View Code

 

D. Yet Another Subarray Problem 思维 难

标签:ons   iostream   gif   subarray   std   sum   tar   force   The   

原文地址:https://www.cnblogs.com/EchoZQN/p/11230583.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!