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;

}

 

你可能感兴趣的:(poj)