POJ 2373
原本一道挺简单的DP题,思路有了,运用单调队列,但在写单调队列时写挫了。。。
这道题只需要计算偶数位置的即可,这是显而易见的,我有注意过这情况,写的时候却没在意。。。--!
加入队列的元素应该当前now之前的now-2*A的元素,我开始不是每计算一个now位置就加入now-2*A的元素,搞得不是O(L)的复杂度。这次吸取教训了。。记得DP时使用单调队列一般每计算一个位置加入一个元素。
PS:
又回想起之前比赛,感觉很害怕。。希望自己加油吧。
我的代码:不知为何没能过。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#include <string.h>
#include <queue>
#include <cmath>
#include <vector> using namespace std;
const int N=1000100;
const int inf=1<<30; int dp[N],que[N],f,l,p;
struct Node{
int l,r;
Node(){l=0,r=0;}
Node(int ll,int rr){l=ll,r=rr;}
bool operator <(const Node &a)const{
if(l<a.r) return true;
return false;
}
};
Node node[1010]; int n,L,a,b; void Mergeinter(){
/* int top=0;
for(int i=1;i<n;i++){
if(node[i].l<node[top].r&&node[top].r<node[i].r)
node[top].r=node[i].r;
else if(node[i].l<node[top].r&&node[top].r>=node[i].r) continue;
else{
top++;
node[top].l=node[i].l;
node[top].r=node[i].r;
}
}
n=top;*/
int top=0;
int l=node[0].l,r=node[0].r;
for(int i=1;i<n;i++){
if(node[i].l<r){
r=max(r,node[i].r);
}else{
node[top++]=Node(l,r);
l=node[i].l;
r=node[i].r;
}
}
node[top++]=Node(l,r);
n=top;
} void Pop(int now){
while(f<l){
if(now-que[f]<=b) break;
f++;
}
} void Push(int now){
while(f<l){
if(dp[que[l-1]]<dp[now-a]) break;
l--;
}
que[l++]=now-a;
} int main(){
while(scanf("%d%d",&n,&L)!=EOF){
scanf("%d%d",&a,&b);
for(int i=0;i<n;i++){
scanf("%d%d",&node[i].l,&node[i].r);
}
if(L%2==1){ printf("-1\n");continue; }
f=l=p=0;
sort(node,node+n);
Mergeinter();
a*=2;b*=2;
dp[0]=0;
for(int i=2;i<a;i+=2) dp[i]=inf;
for(int i=a;i<=L;i+=2){
Pop(i);
Push(i);
while(p<n&&node[p].r<=i) p++;
if(p<n&&node[p].l<i||dp[que[f]]==inf) dp[i]=inf;
else dp[i]=dp[que[f]]+1;
}
if(dp[L]==inf) printf("-1\n");
else printf("%d\n",dp[L]);
}
return 0;
}
引用别人的:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;
const int MAX=1001000;
const int oo=0x3f3f3f3f;
int dp[MAX];
struct Seg{
int x,y;
Seg(int x=0,int y=0):x(x),y(y){}
bool operator<(const Seg& seg) const{
return x<seg.x;
}
}seg[1100];
int q[MAX],id[MAX],f,b;
int merge(int n){
int top=0;
sort(seg,seg+n);
int l=seg[0].x,r=seg[0].y;
for(int i=1;i<n;i++){
if(seg[i].x<r){
r=max(r,seg[i].y);
}else{
seg[top++]=Seg(l,r);
l=seg[i].x;
r=seg[i].y;
}
}
seg[top++]=Seg(l,r);
return top;
}
int main(){
int n,L,l,r,p;
scanf("%d%d",&n,&L);
if(L&1){
printf("%d\n",-1);
return 0;
}
scanf("%d%d",&l,&r);
for(int i=0;i<n;i++){
scanf("%d%d",&seg[i].x,&seg[i].y);
}
n=merge(n);
l<<=1;
r<<=1;
dp[0]=0;
f=b=0;
p=0;
dp[0]=0;
for(int i=2;i<l;i+=2)dp[i]=oo; //start with 2.
for(int i=l;i<=L;i+=2){
while(f!=b&&i-id[f]>r)f++;
while(f!=b&&q[b-1]>=dp[i-l])b--;
id[b]=i-l;
q[b++]=dp[i-l];
while(p<n&&seg[p].y<=i)p++;
if(p<n&&seg[p].x<i||q[f]==oo)dp[i]=oo; //if q[f] is oo, not to set dp[i] = q[f]+1.
else dp[i]=q[f]+1;
}
//for(int i=0;i<=L;i+=2)printf("%d ",dp[i]==oo?-1:dp[i]);puts("");
printf("%d\n",dp[L]==oo?-1:dp[L]); return 0;
}
POJ 2373的更多相关文章
- POJ 2373 Dividing the Path(DP + 单调队列)
POJ 2373 Dividing the Path 描述 农夫约翰的牛发现,在他的田里沿着山脊生长的三叶草是特别好的.为了给三叶草浇水,农夫约翰在山脊上安装了喷水器. 为了使安装更容易,每个喷头必须 ...
- [POJ 2373][BZOJ 1986] Dividing the Path
Link: POJ 2373 传送门 Solution: 一开始想错方向的一道简单$dp$,不应该啊…… 我一开始的想法是以$cows' ranges$的节点为状态来$dp$ 但明显一个灌溉的区间的两 ...
- poj 2373 Dividing the Path
Dividing the Path Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 2858 Accepted: 1064 ...
- poj 2373 单调队列优化背包
思路:我们用单调队列保存2*b<=i-j<=2*a中的最大值.那么队列头就是最大值,如果队头的标号小于i-2*b的话,就出队,后面的肯定用不到它了. #include<iostrea ...
- POJ 2373 Yogurt factory
简单DP. 这周所用的实际花费是上一周的花费+S与这周费用的较小值. #include<cstdio> #include<cstring> #include<cmath& ...
- Dividing the Path POJ - 2373(单调队列优化dp)
给出一个n长度的区间,然后有一些小区间只能被喷水一次,其他区间可以喷水多次,然后问你要把这个区间覆盖起来最小需要多少喷头,喷头的半径是[a, b]. 对于每个只能覆盖一次的区间,我们可以把他中间的部分 ...
- Dividing the Path POJ - 2373 dp
题意:你有无数个长度可变的区间d 满足 2a<=d<=2b且为偶数. 现在要你用这些区间填满一条长为L(L<1e6且保证是偶数)的长线段. 满足以下要求: 1.可变区间之间不能有 ...
- POJ 2373 Dividing the Path (单调队列优化DP)题解
思路: 设dp[i]为覆盖i所用的最小数量,那么dp[i] = min(dp[k] + 1),其中i - 2b <= k <= i -2a,所以可以手动开一个单调递增的队列,队首元素就是k ...
- POJ 2373 单调队列优化DP
题意: 思路: f[i] = min(f[j]) + 1; 2 * a <= i - j <= 2 *b: i表示当前在第i个点.f[i]表示当前最少的线段个数 先是N^2的朴素DP(果断 ...
随机推荐
- 【转】UINavigationController 直接返回到第一级目录
原文网址:http://blog.csdn.net/justinjing0612/article/details/7360852 [self.navigationController popViewC ...
- PCB MVC启动顺序与各层之间数据传递对象关系
准备着手基于MVC模式写一套Web端流程指示查看,先着手开发WebAPI打通数据接口,后续可扩展手机端 这里将MVC基本关系整理如下: 一.MVC启动顺序 二.MVC各层之间数据传递对象关系
- Spell checker(串)
http://poj.org/problem?id=1035 题意:给定一个单词判断其是否在字典中,若存在输出"%s is correct",否则判断该单词删掉一个字母,或增加一个 ...
- 14招搞定JavaScript调试
14招搞定JavaScript调试 译者按: 很多时候,大家可能只是依靠console.log来调试JavaScript代码,这样做的局限性不言而喻,这篇博客将教你几招实用的调试技巧. 原文: The ...
- Python 40 数据库-约束
约束 1.什么是约束 ? 除了数据类型以外额外添加的约束 2.为什么要使用约束 ? 为了保证数据的合法性 完整性 分类: 1.not null 非空约束,数据不能为空----------------- ...
- java.util.concurrent常用类(CountDownLatch,Semaphore,CyclicBarrier,Future)
CyclicBarrier CyclicBarrier是用来一个关卡来阻挡住所有线程,等所有线程全部执行到关卡处时,再统一执行下一步操作.假设一个场景:每个线程代表一个跑步运动员,当运动员都准备好后, ...
- jboss-as-7.1.1.Final配置Jndi数据源(以mysql为例)
1.获取mysql驱动,可以从mysql官方网站下载: http://dev.mysql.com/downloads/connector/j/ 2.进入jboss-as-7安装目录下的modules目 ...
- 酷派 5267 刷入第三方 recovery教程 刷机 ROOT
准备工作: 一台电脑: 酷派5267手机: 一张内存卡: 下载好刷机资料: http://pan.baidu.com/s/1i4LoVh7 备用下载: http://pan.baidu.com/s/ ...
- 用SQL Server查询所有数据并显示
利用SQL Server查询数据,并把所有数据显示在页面上. "%> <%@page import="jdbc.sqlServer"%> <%@p ...
- OpenCV:Python3使用OpenCV
Python3使用OpenCV安装过程应该是这样的,参考:http://blog.csdn.net/lixintong1992/article/details/61617025 ,使用conda ...