1 条题解

  • 1
    @ 2024-12-11 16:32:03

    暴力枚举:第一个 forfor 枚举区间长度,第二个 forfor 枚举区间起点,第三个 forfor 累加区间和为ssss 不断取 maxmax ,时间复杂度为 O(nm2)O(nm^2), 超时。

    考虑优化,由于累加我们可以想到前缀和,s[n]s[n] 表示的是前 nn 个元素的和,O(1)O(1) 时间便可快速求解区间和,此时减去一维累加操作,时间复杂度为 O(nm)O(nm), 仍然超时。

    继续优化,由于本题要求长度不超过 mm,观察发现对于长度为 mm 的区间 [st,ed][st, ed],且必包含元素 eded 最优解即为 seds_{ed} 减去前 mm 个元素的最小值(会向前多减一个),由局部推广到整体,线性扫描整个数组,求解任意一个区间长度为 mm 的最优解不断取 maxmax,便是最终答案。这一步成其实是将问题转化为滑动窗口求最值问题,时间复杂度为 O(n)O(n)。

    #include <iostream>
    using namespace std;
    const int N = 300010;
    int n, m;
    int a[N], s[N];
    int q[N];
    int res;
    int main()
    {
        cin >> n >> m;
        for(int i = 1; i <= n; ++ i)
        {
            cin >> a[i];
            s[i] = s[i - 1] + a[i];
        }//求前缀和
        int hh = 0, tt = -1;
        for(int i = 1; i <= n; ++ i)
        {
            if(i - q[hh] > m) ++ hh;//由于是用到前m个的最值,所以长度为m+1仍然合法
            res = max(res, s[i] - s[q[hh]]);
    
            while(hh <= tt && s[q[tt]] >= s[i]) -- tt;//滑动窗口存的是下标,所以额外嵌套s[q[tt]]
            q[++ tt] = i;//存窗口所有元素的下标
        }
        cout << res << '\n';
        return 0;
    }
    
    • 1

    信息

    ID
    5522
    时间
    1000ms
    内存
    256MiB
    难度
    9
    标签
    递交数
    16
    已通过
    3
    上传者