您的位置:首页 > 产品设计 > UI/UE

HDU 3415 Max Sum of Max-K-sub-sequence

2014-08-21 10:22 218 查看
http://acm.hdu.edu.cn/showproblem.php?pid=3415

本题是需要单调队列的动态规划问题,求环上长度为K以内的且和最大的区间。

单调队列的队头维护的是满足在区间内部的且和最小的下标,这样才能得到最大和sum,因为和是sum[i] - sum[Q.front()]。使用双端队列实现单调队列单调性的维护。a的下标入队时依次弹出比a大的所有元素再将a的下标从队尾加入队列,以维持队列的单调性。

实现如下:

for(int i=1; i<=N; i++){
            while(!Q.empty() && sum[i -1] < sum[Q.back()])
                Q.pop_back();
            while(!Q.empty() && Q.front() < i - K)
                Q.pop_front();
            Q.push_back(i - 1);
        }

AC代码参考:

#include <queue>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>

using namespace std;

const int INF = 0x3f3f3f3f;

int a[200010],sum[200010];
int main(){
//    freopen("in.txt","r",stdin);
    int cas;
    scanf("%d",&cas);
    while(cas--){
        int N,K;
        scanf("%d%d",&N,&K);
        sum[0] = 0;
        for(int i=1; i<=N; i++){
            scanf("%d",&a[i]);
            sum[i] = a[i] + sum[i - 1];
        }
        for(int i=N+1; i<N+K; i++)
            sum[i] = sum[i - 1] + a[i - N];
        int temp = N;
        N = N + K - 1;
        deque <int> Q;
        Q.clear();
        int ans = -INF,start,en;
        for(int i=1; i<=N; i++){
            while(!Q.empty() && sum[i - 1] < sum[Q.back()])
                Q.pop_back();
            while(!Q.empty() && Q.front() < i - K)
                Q.pop_front();
            Q.push_back(i - 1);
            if(sum[i] - sum[Q.front()] > ans){
                ans = sum[i] - sum[Q.front()];
                start = Q.front() + 1;
                en = i;
            }
        }
        if(en > temp)
            en %= temp;
        cout << ans << " " << start << " " << en << endl;
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: