MT3046 愤怒的象棚

思路:

a[]存愤怒值;b[i]存以i结尾的,窗口里的最大值;c[i]存以i结尾的,窗口里面包含✳的最大值。

(✳为新大象的位置)

例:1 2 3 4 ✳ 5 6 7 8 9

则ans的计算公式=b3+b4+c4+c5+c6+b7+b8+b9;

b3为max[1 2 3];  b4为max[2 3 4];

c4为max[3 4 ✳]; c5为max[4 ✳ 5]; c6为max[✳ 5 6];

b7为max[5 6 7]; b8为max[6 7 8]; b9为max[7 8 9];

由此可以归纳得到一个公式:n个数,每个窗口长度为m,遍历到i时,ans可以分成三段:①[b(m)+b(m+1)+...+b(i-1)] + ②[c(i-1)+c(i)+...+c(i+m-2)] + ③[b(i+m-1)+...+b(n)]

(求max[]使用单调队列来求,求ans用前缀和)

ans=sumb[i-1]+sumc[i+m-2]-sumc[i-2]+sumb[n]-sumb[i+m-2]

但是还有ans某部分不存在的情况:

当i<=m时,此时①不存在,即ans=sumc[i+m-2]+sumb[n]-sumb[i+m-2]

若i>=n-m+2时,此时③不存在,,即ans=sumb[i-1]+sumc[n]-sumc[i-2]

当i>m&&i<n-m+2时,ans=sumb[i-1]+sumc[i+m-2]-sumc[i-2]+sumb[n]-sumb[i+m-2]

代码:

 

#include <bits/stdc++.h>
using namespace std;
const int N = 5e6 + 10;
int n, m, A, ans = 0;
int a[N], b[N], c[N];
int sumc[N], sumb[N];
void getmax(int n, int m)
{
    deque<int> q;
    for (int i = 1; i <= n; i++)
    {
        if (!q.empty() && q.front() <= i - m)
            q.pop_front();
        while (!q.empty() && a[i] >= a[q.back()])
            q.pop_back();
        q.push_back(i);
        if (i >= m)
        {
            b[i] = a[q.front()];
            sumb[i] = sumb[i - 1] + b[i];
        }
    }
}
void getmax2(int n, int m)
{
    deque<int> q;
    for (int i = 1; i <= n; i++)
    {
        if (!q.empty() && q.front() <= i - m)
            q.pop_front();
        while (!q.empty() && a[i] >= a[q.back()])
            q.pop_back();
        q.push_back(i);
        if (i >= m)
        {
            c[i] = max(A, a[q.front()]);
            sumc[i] = sumc[i - 1] + c[i];
        }
    }
}

int main()
{
    cin >> n >> m >> A;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    getmax(n, m);      // 求b[]
    getmax2(n, m - 1); // 求c[]
    for (int i = 1; i <= n + 1; i++)
    {
        if (i <= m)
        {
            ans = max(ans, sumc[i + m - 2] + sumb[n] - sumb[i + m - 2]);
        }
        else if (i >= n - m + 2)
        {
            ans = max(ans, sumb[i - 1] + sumc[n] - sumc[i - 2]);
        }
        else
        {
            ans = max(ans, sumb[i - 1] + sumc[i + m - 2] - sumc[i - 2] + sumb[n] - sumb[i + m - 2]);
        }
    }
    cout << ans;
    return 0;
}

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值