zoukankan      html  css  js  c++  java
  • HDOJ 3415 Max Sum of MaxKsubsequence(单调队列变型)

    题意:

    给定一个环形数组,求数组中连续长度不超过 K 的最大子段和。

    思路:

    1. 题目中给定的是环形数组,其实可以在数组尾部复制一份原数据,于是把问题规模扩大到了 2 * N,但是方便了解题。

    2. 对数据在加以转换:sum[i] 表示 1~i 数组元素的和,由于题目中给定了数据范围,保证了 int 不会溢出。

    3. 单调队列里面的数据表示 x~x+k 范围内 sum[] 的最小值。于是 sum[x+k+1] - sum[deq[s]] 即是以 x+k+1 为结尾的子序列最大和。

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 100010;
    const int INFS = 0x7fffffff;
    
    int sum[MAXN * 2], deq[MAXN * 2];
    
    int main()
    {
        int cases;
        scanf("%d", &cases);
        while (cases--)
        {
            int N, K;
            scanf("%d %d", &N, &K);
    
            sum[0] = 0;
            for (int i = 1; i <= N; ++i)
            {
                scanf("%d", &sum[i]);
                sum[i+N] = sum[i];
            }
    
            for (int i = 1; i <= 2 * N; ++i)
                sum[i] += sum[i-1];
    
            int s = 0, e = -1;
            int ans = -INFS, beg = 0, end = 0;
    
            for (int i = 0; i < 2 * N; ++i)
            {
                if (i >= K && sum[i-K] == sum[deq[s]])
                    ++s;
    
                while (s <= e && sum[i] < sum[deq[e]])
                    --e;
    
                deq[++e] = i;
    
                if (sum[i+1] - sum[deq[s]] > ans)
                {
                    ans = sum[i+1] - sum[deq[s]];
                    beg = deq[s] + 1, end = i + 1;
                }
            }
            printf("%d %d %d\n", ans, (beg - 1) % N + 1, (end - 1) % N + 1);
        }
        return 0;
    }
  • 相关阅读:
    阿里云SLB的http强制转https
    nginx反向代理springboot的jar包
    阿里云Centos7上添加swap分区
    AWS云怎么删除信用卡账户
    Linux记录别人操作
    Jumpserver里常用的sudo权限
    端口一览表
    网络端口及其详解
    阿里云安全防坑指南
    LINUX添加只读用户(查日志专用)
  • 原文地址:https://www.cnblogs.com/kedebug/p/2935385.html
Copyright © 2011-2022 走看看