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(果断 ...
随机推荐
- PCB 全景图技术实现
为了对3D模型理解更透,这里采用threejs(WebGL第三方库)实现,刚开始学习入门,为了能看明白基本上每行代码都注释. 如果仅仅是为了实现全景图,可以用photo-sphere-viewer.j ...
- JAVA 中进行网络通信时,通信的程序两端要传输的对象,不仅要序列化,而且这个对象所属的类的名字要完全一样,连包的名字都得一样
如上图项目目录,这是一个简易的QQ,客户端登录的时候要传输用户信息到服务器验证,所以两端都会用到User类的对象,但一开始我在Server端的包名是com.qq.server.common,两端的报名 ...
- POJ 2186 Tarjan
题意:有n(n<=10000)头牛,每头牛都想成为最受欢迎的牛,给出m(m<=50000)个关系,如(1,2)代表1欢迎2,关系可以传递,但是不是相互的,那么就是说1欢迎2不代表2欢迎1, ...
- Nmap linux端口扫描神器
#简介 Nmap亦称为Network Mapper(网络映射)是一个开源并且通用的用于Linux系统/网络管理员的工具.nmap用于探查网络.执行安全扫描.网络核查并且在远程机器上找出开放端口.它可以 ...
- layui 时间前后节点验证
var start = { istime: true, format: 'YYYY-MM-DD hh:mm:ss', max: '2099-06-16', istoday: true, choose: ...
- Md2All版本更新记录
Md2All版本更新记录 版本号:V2.8.2更新日期:2018-06-281:结合云图床,解决了Latex公式复制到公众号时有可能报“图片粘贴失败的问题”;2:结合云图床,解决了Latex公式复制到 ...
- 01--Java IO基础
一.java.io包概览 Java IO包主要可以分为如下4类: 基于字节操作的I/O接口:InputStream和OutputStream. 基于字符操作的I/O接口:Writer和Reader 基 ...
- 【PostgreSQL-9.6.3】extract函数
extract函数格式: extract (field from source) extract函数是从日期或者时间数值里面抽取子域,比如年.月.日等.source必须是timestamp.time. ...
- vim之快速跳转
光棍节啦, 淘东西的闲暇上来发vim旅途第一篇日志. 为什么呢? 因为今天是我媳妇的生日, 我用这种只有我知道的方式来纪念一下. ^_^, 宝宝生日快乐! 开篇先说明日志布局, vim学习记录连载中所 ...
- 图像局部显著性—点特征(GLOH)
基于古老的Marr视觉理论,视觉识别和场景重建的基础即第一阶段为局部显著性探测.探测到的主要特征为直觉上可刺激底层视觉的局部显著性--特征点.特征线.特征块. 相关介绍:局部特征显著性-点特征(SIF ...