单调队列优化dp——poj2373 经典

经典老题了,其实数据没那么强

/*
dp[i]表示覆盖了前[0,i]区间的最优解
dp[i]=min(dp[i-j]) 2A<=j<=2B
直接用单调队列优化 
对于奇数坐标,直接忽略就行 
*/
#include<iostream>
#include<queue>
#include<cstring>

using namespace std;
#define N 2000005
#define INF 100000000 

int L,n,A,B,l[N],r[N],dp[N];

int main(){
    cin>>n>>L>>A>>B;
    for(int i=1;i<=n;i++){
        cin>>l[i]>>r[i];
        for(int j=l[i]+1;j<=r[i]-1;j++)
            dp[j]=INF;
    }
    if(L%2 || L<2*A){puts("-1");return 0;}
    
    for(int i=2;i<2*A;i+=2)dp[i]=INF;
    deque<int>q;
    for(int i=2*A;i<=L;i+=2){
        //把i-2B前的元素出队
        while(q.size()){
            int p=q.front();
            if(p<i-2*B){q.pop_front();continue;}
            else break;
        } 
        //把dp[i-2A]入队 
        while(q.size()){
            int p=q.back();
            if(dp[p]>=dp[i-2*A])q.pop_back();
            else break;
        } 
        q.push_back(i-2*A);
        if(dp[i]<INF)dp[i]=dp[q.front()]+1;
    } 
    
    if(dp[L]<INF)cout<<dp[L]<<'\n';
    else cout<<-1<<'\n';
}

 

posted on 2020-03-17 15:28  zsben  阅读(145)  评论(0编辑  收藏  举报

导航