Link:

POJ 2373 传送门

Solution:

一开始想错方向的一道简单$dp$,不应该啊……

我一开始的想法是以$cows' ranges$的节点为状态来$dp$

但明显一个灌溉的区间的两边不一定都在$cows's ranges$上,

因此应该以长为$L$的$field$上的每一个偶数节点为状态来$dp$,

这样转移方程就很容易了:

$dp[i]=min\{ dp[j] \} +1(2*a\le i-j\le 2*b)$

由于$dp[j]$具有决策单调性(对于节点$i$,$k$比$j$更优$(j<k)$,那么对于后面任意一个节点$j$都优于$k$)

于是使用单调队列维护一个$dp$值递增,离起点距离递增的序列,每次弹出$i-q[l]>=2*b$的$l$

为了处理$cows' ranges$上的节点,使用差分将在区间内的节点打上标记,遇到时跳过即可

Note:这里的特判依然要注意,如果对于一个非终点的节点找不到符合的点,不代表无解!跳过即可

Code:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring> using namespace std;
const int MAXN=1e6+; int n,L,a,b,dp[MAXN],pre[MAXN],q[MAXN],l,r; int main()
{
scanf("%d%d%d%d",&n,&L,&a,&b);
for(int i=;i<=n;i++)
{
int x,y;scanf("%d%d",&x,&y);
pre[x+]++;pre[y]--;
if(y-x>*b){printf("-1");return ;}
}
for(int i=;i<=L;i++) pre[i]+=pre[i-]; l=r=;q[]=;
for(int i=*a;i<=L;i+=)
{
if(pre[i]) continue;
while(l<=r && i-q[l]>*b) l++;
if(l>r){printf("-1");return ;}
if(i-q[l]<*a) continue; //对不符合条件的数的处理 dp[i]=dp[q[l]]+;
while(l<=r && dp[i]<dp[q[r]]) r--;q[++r]=i;
}
if(!dp[L]) printf("-1"); //特例处理
else printf("%d",dp[L]);
return ;
}

Review:

(1)还是要对特判细节想清楚啊……

(2)对于有决策单调性的题目想到单调性优化

(3)选择$dp$状态时要考虑状态集是否包含了所有“过程”中的“终点”

(如果按$cows' ranges$选取则不能)

[POJ 2373][BZOJ 1986] Dividing the Path的更多相关文章

  1. POJ 2373 Dividing the Path(DP + 单调队列)

    POJ 2373 Dividing the Path 描述 农夫约翰的牛发现,在他的田里沿着山脊生长的三叶草是特别好的.为了给三叶草浇水,农夫约翰在山脊上安装了喷水器. 为了使安装更容易,每个喷头必须 ...

  2. poj 2373 Dividing the Path

    Dividing the Path Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2858   Accepted: 1064 ...

  3. poj2373 Dividing the Path

    Dividing the Path Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5060   Accepted: 1782 ...

  4. 【POJ】2373 Dividing the Path(单调队列优化dp)

    题目 传送门:QWQ 分析 听说是水题,但还是没想出来. $ dp[i] $为$ [1,i] $的需要的喷头数量. 那么$ dp[i]=min(dp[j])+1 $其中$ j<i $ 这是个$ ...

  5. Dividing the Path POJ - 2373(单调队列优化dp)

    给出一个n长度的区间,然后有一些小区间只能被喷水一次,其他区间可以喷水多次,然后问你要把这个区间覆盖起来最小需要多少喷头,喷头的半径是[a, b]. 对于每个只能覆盖一次的区间,我们可以把他中间的部分 ...

  6. Dividing the Path POJ - 2373 dp

    题意:你有无数个长度可变的区间d  满足 2a<=d<=2b且为偶数. 现在要你用这些区间填满一条长为L(L<1e6且保证是偶数)的长线段. 满足以下要求: 1.可变区间之间不能有 ...

  7. POJ 2373 Dividing the Path (单调队列优化DP)题解

    思路: 设dp[i]为覆盖i所用的最小数量,那么dp[i] = min(dp[k] + 1),其中i - 2b <= k <= i -2a,所以可以手动开一个单调递增的队列,队首元素就是k ...

  8. HDU 3062 && HDU 1824 && POJ 3678 && BZOJ 1997 2-SAT

    一条边<u,v>表示u选那么v一定被选. #include <iostream> #include <cstring> #include <cstdio> ...

  9. [USACO2004][poj2373]Dividing the Path(DP+单调队列)

    http://poj.org/problem?id=2373 题意:一条直线分割成N(<=25000)块田,有一群奶牛会在其固定区域吃草,每1把雨伞可以遮住向左右延伸各A到B的区域,一只奶牛吃草 ...

随机推荐

  1. python 读取数据库中文内容显示一堆问号

    需要在连接数据库时 设置编码格式 def select_db(self,db_name): self.conn = MySQLdb.connect( host = self.ip, port = se ...

  2. python基础实践(四)

    # -*- coding:utf-8 -*-# Author:sweeping-monkwhy = "为什么要组织列表?"print(why)Chicken_soup = &quo ...

  3. 一个初学者的辛酸路程-前端js

    内容回顾: 1.CSS的基本概念: 层叠样式表. 2.CSS的三种书写方式 ① 行内样式 <div style="color: red;">sdfdsf</div ...

  4. JAVA相似算法的运用

    今天要处理问题是把一个产品的名字按照其内容对比文档转换出它的中文名. 但是这个文档感觉不全,产品种类有多又杂. 如果像这样写的话 if(xxx.contains()) else if() ... 不知 ...

  5. Linux查看端口被占用情形

    查看某端口的占用情况: lsof -i:<端口号> 例如:lsof -i:8080 netstat -apn|grep <端口号> 例如: netstat -apn | gre ...

  6. google protobuf 中的proto文件编写规则

    1. 简单介绍 protobuf文件:就是定义你要的消息(类似Java中的类)和消息中的各个字段及其数据类型(类似java类中的成员变量和他的数据类型) 2. Protobuf消息定义 消息由至少一个 ...

  7. Android记事本开发03

    昨天: 生成签名文件及导出apk 遇到的问题: 无. 今天: activity和intent基础

  8. 第十章 用户数据报协议和IP分片

    用户数据报协议和IP分片 UDP是一种保留消息边界的简单的面向数据报的传输层协议.它仅提供差错检测.只是检测,而不是纠正,它只是把应用程序传给IP层的数据发送出去,但是并不会保证数据能够完好无损的到达 ...

  9. 安装bcc

    sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys D4284CDD echo "deb https://repo.i ...

  10. java.net.SocketException: recvfrom failed: EBADF (Bad file descriptor)

    1. 问题说明: 与服务器之间进行socket通信的时候,客户端关闭socket之后,会抛出一个IOException,异常信息如下: java.net.SocketException: recvfr ...