poj 2373 单调队列优化背包

思路:我们用单调队列保存2*b<=i-j<=2*a中的最大值。那么队列头就是最大值,如果队头的标号小于i-2*b的话,就出队,后面的肯定用不到它了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define inf 10000010
#define Maxn 1010
#define Min(a,b) (a)>(b)?(b):(a)
using namespace std;
int dp[1000010],que[1000010],head,rear,interv[1200010];
struct Inter{
    int l,r;
    int operator<(const Inter &temp) const
    {
        return l<temp.l;
    }
}p[Maxn];
int main()
{
    int n,l,i,j,t,a,b;
    while(scanf("%d%d",&n,&l)!=EOF)
    {
        scanf("%d%d",&a,&b);
        memset(interv,1,sizeof(interv));
        for(i=1;i<=n;i++)
        {
            scanf("%d%d",&p[i].l,&p[i].r);
            memset(interv+p[i].l+1,0,(p[i].r-p[i].l-1)*sizeof(interv[0]));
        }
        dp[0]=0;
        head=1,rear=0;
        for(i=2;i<=l;i++)
        {
            dp[i]=inf;
            j=i-2*a;
            if(j<0) continue;
            while(head<=rear&&dp[j]<=dp[que[rear]])
                rear--;
            if(interv[j])
                que[++rear]=j;
            if(que[head]<i-2*b&&head<=rear)
                head++;
            if(!interv[i]||(i&1)) continue;
            if(head<=rear)
            dp[i]=dp[que[head]]+1;
        }
        if(dp[l]>=inf) printf("-1\n");
        else printf("%d\n",dp[l]);
    }
    return 0;
}

 

posted @ 2013-08-05 10:52  fangguo  阅读(265)  评论(0编辑  收藏  举报