现在的位置: 首页 > 综合 > 正文

Sequences hoj 单调队列优化DP

2014年03月06日 ⁄ 综合 ⁄ 共 873字 ⁄ 字号 评论关闭
/*可以用单调队列优化的DP一般是用于限定长度的区间,且区间有整体移动的趋势。即每一个元素是逐次进出区间,且只有一次。这样的题目一般都是有比较明显的模板。下面的这个就是集训的时候学长给的模板。感觉挺好写和理解。不过综合对比时间效率。感觉不一定是最高效的。
题意是给你固定的区间长度范围。求该序列首端和末端的和最大值。
简单。维护一个单调队列进行优化即可。有些细节看代码的注释。*/
#include <iostream>
#include <stdio.h>
#include <cstring>
#define maxn 100010
//#define inf -1000000000
#define inf 0x7fffffff
using namespace std;
struct node
{
    int num,id;
    node() {}
    node(int _num,int _id)
    {
        num=_num;
        id=_id;
    }
} q[maxn];
int dp[maxn];
int a[maxn];
int main()
{
    int n,m,len;
    while(scanf("%d",&len)==1)
    {
        dp[0]=0;
        scanf("%d%d",&n,&m);
        for(int i=1; i<=len; i++)
            if(i<=n-1) dp[i]=inf;//1到n-1没有意义        
        int head=0,rear=0;
        q[rear++]=node(0,1);
        for(int i=1; i<=len; i++)
        {
            scanf("%d",&a[i]);
            if(i>=n)
            {
                while(head<rear&&q[rear-1].num<=dp[i-n]+a[i-n+1]) rear--;//将i-n加入,i-m已经在队列中.
                q[rear++]=node(dp[i-n]+a[i-n+1],i-n);
                while(head<rear&&i-q[head].id>m) head++;//注意是>m..知道找到<=m时跳出.<=m是我们需要的情况
                dp[i]=q[head].num+a[i];
            }
        }
        printf("%d\n",dp[len]);
    }
    return 0;
}

抱歉!评论已关闭.