POJ 2373 Dividing the Path

来源:互联网 发布:联通怎么重置手机网络 编辑:程序博客网 时间:2024/04/27 15:48

题意:长度为L的区间,有N头牛有各自喜欢活动的区间(Si,Ei),喷水的喷头只能安装在整数点上,且它能喷到的半径在[A,B]之间,现在要求:用最少的喷水头不交叉的覆盖整个L,并且满足每头牛喜欢活动的区间里只有一个喷头再喷。

题解:线段树优化DP,dp[i]代表喷完前i个地方所需要的最少喷头数,那么dp[i]=min(dp[j]+1),i-2b<=j<=i-2a,用线段树记录[i-2b,i-2a]的最小值就行了。

#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int L=1000005,inf=0x3f3f3f3f;bool ck[L];struct Line{    int left,right,val;}line[L*4];void build(int now,int left,int right){    line[now].left=left;    line[now].right=right;    line[now].val=inf;    if(left==right)return;    build(now*2,left,(left+right)>>1);    build(now*2+1,(left+right)/2+1,right);}void updata(int now,int pos,int val){    int ll=line[now].left,rr=line[now].right,mid;    if(ll==pos&&rr==pos)    {        line[now].val=min(line[now].val,val);        return;    }    mid=(ll+rr)>>1;    if(pos<=mid)        updata(now*2,pos,val);    else        updata(now*2+1,pos,val);    line[now].val=min(line[now*2].val,line[now*2+1].val);}int getmin(int now,int left,int right){    int ll=line[now].left,rr=line[now].right,mid;    if(ll==left&&rr==right)        return line[now].val;    mid=(ll+rr)>>1;    if(right<=mid)        return getmin(now*2,left,right);    else if(left>mid)        return getmin(now*2+1,left,right);    else        return min(getmin(now*2,left,mid),getmin(now*2+1,mid+1,right));}int main(){    int n,len,a,b,ans;    while(scanf("%d%d",&n,&len)!=EOF)    {        build(1,0,len/2);        scanf("%d%d",&a,&b);        memset(ck,true,sizeof(ck));        for(int i=0,x,y;i<n;i++)        {            scanf("%d%d",&x,&y);            memset(ck+x+1,false,(y-x-1)*sizeof(bool));        }        updata(1,0,0);        for(int i=a*2;i<=len;i+=2)        {            if(ck[i])            {                int x=i/2-b,y=i/2-a,tp;                x=max(0,x);                tp=getmin(1,x,y);                if(tp==inf)                    tp--;                updata(1,i/2,tp+1);            }        }        ans=getmin(1,len/2,len/2);        printf("%d\n",ans<inf?ans:-1);    }    return 0;}