DP/单调队列优化


  首先不考虑奶牛的喜欢区间,dp方程当然是比较显然的:$ f[i]=min(f[k])+1,i-2*b \leq k \leq i-2*a $  当然这里的$i$和$k$都是偶数啦~这个应该很好理解吧……每次喷灌的都是一个偶数长度的区间嘛……

  那么加上奶牛的喜欢区间的话,只需这样:当$ i>cow[j].x $时,令$ i=cow[j].y , j++$ 也就是说中间的位置全部不考虑放喷灌器。

  显然我们对于每个节点的 k 是可以用单调队列维护的!嗯看到这里的同学可以先自己试着去写写看啦~

  如果过了样例不要着急,来试试我这组数据:

2 16
2 4
7 8
6 12

Trick:

  每个奶牛的喜欢区间是一个【开区间】!分界点是可以被不同的喷灌器灌溉的(仔细看看样例的图)

  一开始英文题面嘛……看了中文没细看英文……没看到还有【不合法情况输出-1】so sad……

  每个f[i]不能刚算出来就弹队尾+进队尾,因为此时下一个位置为 i+2 ,可能会把能够转移到i+2的合法状态弹出去,而f[i]是不能转移到f[i+2]的!(因为有a的限制)所以会造成f[i+2]计算错误(当然f[l]就也有可能出错了。

  事实上由于我们维护的队列是一个合法状态区间,所以目前不合法的状态不应该进队,而是应该在每次更新f[i]之前让 f[i-2*a] 进队,这样可以保证队列中所有节点都为合法状态。

  然而!!刚才那种做法会有漏洞!因为我们会在遇到奶牛的喜欢区间的时候跳!过!去!所以一些合法状态就会来不及进队(比如我给的数据中的f[6]……所以在遇到奶牛区间的时候要将这个区间内所有合法的状态进队(当然要维护队列单调性了……需要弹队尾)

 /**************************************************************
Problem: 1986
User: Tunix
Language: C++
Result: Accepted
Time:40 ms
Memory:9092 kb
****************************************************************/ //POJ 2373
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
int getint(){
int v=,sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
return v*=sign;
}
const int N=1e6+,INF=~0u>>;
typedef long long LL;
/******************tamplate*********************/
//#define debug
struct Cow{
int x,y;
Cow(){}
bool operator < (const Cow &b)const{
return x<b.x || (x==b.x && y<b.y);
}
}cow[];
int f[N],n,l,a,b;
int q[N];
int main(){
#ifndef ONLINE_JUDGE
freopen("2373.in","r",stdin);
// freopen("2373.out","w",stdout);
#endif
n=getint(); l=getint(); a=getint(); b=getint();
F(i,,n) cow[i].x=getint(),cow[i].y=getint();
sort(cow+,cow+n+);
#ifdef debug
F(i,,n) printf("%d %d\n",cow[i].x,cow[i].y);
cout <<endl;
#endif
int j=;
F(i,,l) f[i]=INF;
int st=,ed=;
f[]=;
q[ed++]=;
for(int i=;i<=l;i+=){
while(i>cow[j].x && j<=n){
int last=i;
i=max(i,(cow[j].y+)/*),j++;
for(int I=last;I<=i;I+=)
if (f[I-*a]!=INF){
while(st<ed && f[q[ed-]]>f[I-*a]) ed--;
q[ed++]=I-*a;
}
}
while(st<ed && q[st]<i-*b) st++;
if(f[i-*a]!=INF){
while(st<ed && f[q[ed-]]>f[i-*a]) ed--;
q[ed++]=i-*a;
}
if (st<ed && i-q[st]>=*a) f[i]=f[q[st]]+;
}
#ifdef debug
F(i,,l) printf("%d ",f[i]==INF ? - : f[i]);
cout <<endl;
#endif
printf("%d\n",f[l]==INF ? - : f[l]);
return ;
}

【BZOJ】【1986】【USACO 2004 Dec】/【POJ】【2373】划区灌溉的更多相关文章

  1. BZOJ 4094 USACO 2013 Dec. Optimal Milking

    线段树 每个节点保存4个值,both表示左右端点都取,neither表示左右端点都不取,left表示只取左端点,right表示只取右端点. 维护的特殊姿势: $cur$的$both=max(ls.l+ ...

  2. BZOJ 1606 USACO 2008 Dec. 购买干草

    [题意概述] 有n件物品,每件物品有体积Vi,背包容量为C,问最多可以装多少体积的物品 [题解] 显然是个无限背包嘛.. 直接做背包DP就好 注意无限背包的写法和01背包的区别 #include< ...

  3. BZOJ1986: [USACO2004 Dec] Dividing the Path 划区灌溉

    L<=1000000的土地上用长度在2*A~2*B的线段覆盖所有点,且给定n<=1000个区间,每个区间上只允许有一条线段,求最少多少线段,无解-1. f[i]表示填前i个土地最少线段,f ...

  4. 【Noip模拟 20160929】划区灌溉

    题目描述 约翰的奶牛们发现山脊上的草特别美味.为了维持草的生长,约翰打算安装若干喷灌器. 为简化问题,山脊可以看成一维的数轴,长为L(1≤L≤1,000,000)L(1≤L≤1,000,000),而且 ...

  5. [POJ 2373][BZOJ 1986] Dividing the Path

    Link: POJ 2373 传送门 Solution: 一开始想错方向的一道简单$dp$,不应该啊…… 我一开始的想法是以$cows' ranges$的节点为状态来$dp$ 但明显一个灌溉的区间的两 ...

  6. USACO翻译:USACO 2013 DEC Silver三题

    USACO 2013 DEC SILVER 一.题目概览 中文题目名称 挤奶调度 农场航线 贝西洗牌 英文题目名称 msched vacation shuffle 可执行文件名 msched vaca ...

  7. USACO翻译:USACO 2014 DEC Silver三题

    USACO 2014 DEC SILVER 一.题目概览 中文题目名称 回程 马拉松 奶牛慢跑 英文题目名称 piggyback marathon cowjog 可执行文件名 piggyback ma ...

  8. poj 2373 Dividing the Path

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

  9. bzoj:1675 [Usaco2005 Feb]Rigging the Bovine Election 竞选划区

    Description It's election time. The farm is partitioned into a 5x5 grid of cow locations, each of wh ...

随机推荐

  1. [leetcode]_K Sum 问题

    问题:K Sum问题是一个问题系列,在一个数组中找K个数的和能够满足题目中要求.从2 Sum 到 3 Sum , 3 Sum Clozet , 4 Sum..解法虽一开始不容易想到,但get到解题技能 ...

  2. [leetcode]_Symmetric Tree

    第二道树的题目,依旧不会做,谷歌经验. 题目解释: give you a tree , judge if it is a symmetric tree. 思路:我以为要写个中序遍历(进阶学习非递归算法 ...

  3. php读取excel文件 更新修改excel

    php读取excel文件示例,还有更新修改功能. 代码: //模板存放目录 $dir = $DOCUMENT_ROOT.'/backoffice/admin/oemcheck/'; $template ...

  4. PHP-You don’t have permissions to access xxx on this server!

    问题如下图:   如果你是想要查看目录下的每一个文件,那么你需要修改一下httpd-conf配置文件,也就是apache的配置文件,以phpStudy2013为例,如下图打开: 然后找到如下部分,添加 ...

  5. 用VBA计算WPS 表格ET EXCEL中的行数和列数的多重方法

    用VBA计算WPS 表格ET EXCEL中的行数和列数 每种方法中上面的是Excel的行数,下面的是Excel的列数. 方法1: ActiveSheet.UsedRange.Rows.Count Ac ...

  6. Python 2.7的安装(64位win10)

    Python 2.7.12 下载地址:https://www.python.org/downloads/release/python-2712/ 安装路径D:\Program Files\Python ...

  7. Python学习教程(learning Python)--1.2.4 Python格式化输出科学计数

    Python在浮点数据输出时,可以采用科学计数法的方式输出. 现举两个例子说明一下如何使用. eg1. 无精度要求的科学计数法浮点数据输出 >>> print(format(1234 ...

  8. bat文件编写(无线承载网络设置)

    就弄个例子,自己看执行效果,然后模仿写就行. 1)获取当前时间: @echo off set YEAR=%date:~0,4% set MONTH=%date:~5,2% set DAY=%date: ...

  9. FPGA保留信号的语句

    (*synthesis,keep*) (*synthesis,probe_port,keep *) 例:(*synthesis,probe_port,keep *) wire e; 可用于wire型和 ...

  10. GCC编译默认的头文件搜索路径

    对于c语言来说: gcc -xc -E -v - 截图: 对于c++来说: gcc -xc++ -E -v - 截图: gcc的arg和opt解释: 后面一干啥作用暂时不知道