正题
题目链接:http://poj.org/problem?id=2373
题目大意
长度为L,要求每个区域都被洒水器覆盖,而且在每只奶牛的喜爱区域只能由一个洒水器覆盖,洒水器必须放在整数点,喷洒半径只能在a∼ba\sim ba∼b区间。
解题思路
我们考虑dp,我可以先想O(n2)O(n^2)O(n2)的。
fi=min{fj}+1(i−2b≤j≤i−2a)f_i=min\{f_j\}+1\ \ \ (i-2b≤j≤i-2a)fi=min{fj}+1 (i−2b≤j≤i−2a)
然后我们可以用单调队列维护一下区间。
然后我思考奶牛的问题,奶牛所在的区间不可以有洒水器的中断,而fif_ifi表示的是最后一个洒水器在iii位置中断需要的最少洒水器数量,所以我们保证在奶牛喜爱的区域再往内一圈fif_ifi的值都为infinfinf就好了。
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]);//输出
}