题目: 约翰的奶牛们发现山督上的草特别美味.为了维持草的生长,约翰打算安装若干喷灌器.为简化问题,山脊可以看成一维的数轴,长为L(1≤L≤10^6),而且L-定是一个偶数.每个喷灌器可以双向喷灌,并有确定的射程,该射程不短于A,不长于B,A,B(1≤A≤B≤103)都是给出的正整数.它所在位置的两边射程内,都属它的灌溉区域.现要求山脊的每一个区域都被灌溉到,而且喷灌器的灌溉区域不允许重叠, 约翰有N(1≤N≤10^3)只奶牛,每一只都有特别喜爱的草区,第i奶牛的草区是[Si,Ei],不同奶牛的草区可以重叠.现要求,每只奶牛的草区仅被一个喷灌器灌溉. 寻找最少需要的喷灌器数目.
题解:枚举每个浇灌区间的右端i当然浇灌位置只能是偶数,然后标记一下这个位置能否放入浇灌器,最后求出的浇灌区间的左端就是[max(i-2*b,0),i-2*a]注意的是如果i-2*a<0那个么这个i绝对不能当浇灌区间的右端点,最后在放到第i个位置需要浇灌器的数目就是区间[max(i-2*b,0),i-2*a]中放置用了最少浇灌器的数目加一,因为恶劣的情况下区间可能会很大那可能会超时那么需要用线段树维护一下区间的最小值
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define ls 2*rt
#define rs 2*rt|1
#define mid (L+R)/2
#define lson ls,L,mid
#define rson rs,mid+1,R
const int mx = 1e6+5;
const int inf = 0x3f3f3f3f;
struct node{
int s,e;
}p[1005];
int T[mx<<2];
int dp[mx];
int vis[mx];
void update(int rt,int L,int R,int x,int v){
if(L==R){
T[rt] = min(T[rt],v);
return;
}
if(x>mid) update(rson,x,v);
else update(lson,x,v);
T[rt] = min(T[ls],T[rs]);
}
int query(int rt,int L,int R,int l,int r){
if(L>=l&&R<=r)
return T[rt];
if(l>mid) return query(rson,l,r);
else if(r<=mid) return query(lson,l,r);
else
return min(query(lson,l,mid),query(rson,mid+1,r));
}
int main(){
int a,b;
int n,l;
while(scanf("%d%d",&n,&l)!=EOF){
scanf("%d%d",&a,&b);
memset(T,inf,sizeof(T));
memset(dp,inf,sizeof(dp));
memset(vis,0,sizeof(vis));
for(int i = 0; i < n; i++){
scanf("%d%d",&p[i].s,&p[i].e);
vis[p[i].s+1]++;
vis[p[i].e]--;
}
for(int i = 1; i <= l; i++)
vis[i] += vis[i-1];
update(1,0,l,0,0);
dp[0] = 0;
for(int i = 2; i <= l; i+=2)
if(!vis[i]){
int x = i-2*a;
int y = i-2*b;
if(x<0&&y<0)
continue;
y = max(y,0);
dp[i] = min(dp[i],query(1,0,l,y,x)+1);
update(1,0,l,i,dp[i]);
}
if(dp[l]>=inf) puts("-1");
else printf("%d\n",dp[l]);
}
return 0;
}