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;
    }
  • 相关阅读:
    数组下标索引的循环原来可以这样写
    移位运算>>与>>>
    java调用redis的多种方式与心得
    $.ajax传输js数组,spring接收异常
    div背景css样式笔记
    js监听网页页面滑动滚动事件,实现导航栏自动显示或隐藏
    设置系统时区
    安装与配置文本编辑器vim
    添加阿里云数据源
    spring controller获取web前端post数据乱码解决
  • 原文地址:https://www.cnblogs.com/kedebug/p/2935385.html
Copyright © 2011-2022 走看看