POJ2373-Dividing the Path【单调队列优化dp】

正题

题目链接:http://poj.org/problem?id=2373


题目大意

长度为L,要求每个区域都被洒水器覆盖,而且在每只奶牛的喜爱区域只能由一个洒水器覆盖,洒水器必须放在整数点,喷洒半径只能在 a b 区间。


解题思路

我们考虑dp,我可以先想 O ( n 2 ) 的。

f i = m i n { f j } + 1       ( i 2 b j 1 2 a )

然后我们可以用单调队列维护一下区间。
然后我思考奶牛的问题,奶牛所在的区间不可以有洒水器的中断,而 f i 表示的是最后一个洒水器在 i 位置中断需要的最少洒水器数量,所以我们保证在奶牛喜爱的区域再往内一圈 f i 的值都为 i n f 就好了。


code

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
deque<int> q;
int n,l,a,b,w[1000010],f[1000010],x,y,sum;
int main()
{
    scanf("%d%d%d%d",&n,&l,&a,&b);
    b=2*b;a=2*a;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&x,&y);
        w[x+1]++;w[y]--;//标记
    }
    for(int i=2;i<=l;i+=2){
        sum+=w[i]+w[i-1];//记录前缀和
        while(!q.empty()&&i-b>q.front())
          q.pop_front();//维护区域
        int addn=i-a;//维护区域
        if(addn>=0)
        {
          while(!q.empty()&&f[q.back()]>=f[addn])
            q.pop_back();//维护单调性
          q.push_back(addn);//加入队列
        }
        if(!q.empty()&&f[q.front()]<inf&&!sum) 
          f[i]=f[q.front()]+1;//有值
        else f[i]=inf;//无值
    }
    printf("%d",f[l]==inf?-1:f[l]);//输出
}

猜你喜欢

转载自blog.csdn.net/Mr_wuyongcong/article/details/81706626