洛谷P2698 花盆Flowerpot【单调队列】
题目描述
Farmer John has been having trouble making his plants grow, and needs your help to water them properly. You are given the locations of N raindrops (1 <= N <= 100,000) in the 2D plane, where y represents vertical height of the drop, and x represents its location over a 1D number line:

Each drop falls downward (towards the x axis) at a rate of 1 unit per second. You would like to place Farmer John's flowerpot of width W somewhere along the x axis so that the difference in time between the first raindrop to hit the flowerpot and the last raindrop to hit the flowerpot is at least some amount D (so that the flowers in the pot receive plenty of water). A drop of water that lands just on the edge of the flowerpot counts as hitting the flowerpot.
Given the value of D and the locations of the N raindrops, please compute the minimum possible value of W.
老板需要你帮忙浇花。给出N滴水的坐标,y表示水滴的高度,x表示它下落到x轴的位置。
每滴水以每秒1个单位长度的速度下落。你需要把花盆放在x轴上的某个位置,使得从被花盆接着的第1滴水开始,到被花盆接着的最后1滴水结束,之间的时间差至少为D。
我们认为,只要水滴落到x轴上,与花盆的边沿对齐,就认为被接住。给出N滴水的坐标和D的大小,请算出最小的花盆的宽度W。
输入输出格式
输入格式:
第一行2个整数 N 和 D。
第2.. N+1行每行2个整数,表示水滴的坐标(x,y)。
输出格式:
仅一行1个整数,表示最小的花盆的宽度。如果无法构造出足够宽的花盆,使得在D单位的时间接住满足要求的水滴,则输出-1。
输入输出样例
说明
【样例解释】
有4滴水, (6,3), (2,4), (4,10), (12,15).水滴必须用至少5秒时间落入花盆。花盆的宽度为2是必须且足够的。把花盆放在x=4..6的位置,它可以接到1和3水滴, 之间的时间差为10-3 = 7满足条件。
【数据范围】
40%的数据:1 ≤ N ≤ 1000,1 ≤ D ≤ 2000;
100%的数据:1 ≤ N ≤ 100000,1 ≤ D ≤ 1000000,0≤x,y≤10^6。
题意:
用一个宽度最小的花盆接雨滴,使得这个区间内的雨滴的纵坐标最大值和最小值之差大于等于d
思路:
一眼思路是用线段树维护区间最大值和最小值,二分答案。当然T了,而且WA,才拿了20分。好菜啊。
讲道理顶多会T,怎么会WA呢我好菜啊哭。
#include <iostream>
#include <set>
#include <cmath>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define inf 0x7f7f7f7f const int maxn = 1e5 + ;
const int maxd = 1e6 + ;
int n, d, mmx, mmin;
int height[maxd];
int tree_max[maxd << ], tree_min[maxd << ]; void pushup(int rt)
{
tree_max[rt] = max(tree_max[rt << ], tree_max[rt << | ]);
tree_min[rt] = min(tree_min[rt << ], tree_min[rt << | ]);
} void build(int rt, int l, int r)
{
if(l == r){
if(height[l] == -){
tree_max[rt] = -inf;
tree_min[rt] = inf;
}
else{
tree_max[rt] = tree_min[rt] = height[l];
}
return;
}
int mid = (l + r) / ;
build(rt << , l, mid);
build(rt << | , mid + , r);
pushup(rt);
} int query_max(int L, int R, int l, int r, int rt)
{
if(L <= l && R >= r){
return tree_max[rt];
}
int mid = (l + r) / ;
int res = -inf;
if(L <= mid){
res = max(res, query_max(L, R, l, mid, rt << ));
}
if(R > mid){
res = max(res, query_max(L, R, mid + , r, rt << | ));
}
return res;
} int query_min(int L, int R, int l, int r, int rt)
{
if(L <= l && R >= r){
return tree_min[rt];
}
int mid = (l + r) / ;
int res = inf;
if(L <= mid){
res = min(res, query_min(L, R, l, mid, rt << ));
}
if(R > mid){
res = min(res, query_min(L, R, mid + , r, rt << | ));
}
return res;
} bool check(int len)
{
for(int i = mmin; i <= mmx; i++){
//cout<<query_max(i, i + len, 1, mmx, 1)<<endl;
//cout<<query_min(i, i + len, 1, mmx, 1)<<endl;
if(query_max(i, i + len, , mmx, ) - query_min(i, i + len, , mmx, ) >= d)return true;
}
return false;
} int main()
{
scanf("%d%d", &n, &d);
mmx = -inf;
mmin = inf;
memset(tree_max, -inf, sizeof(tree_max));
memset(tree_min, inf, sizeof(tree_min));
memset(height, -, sizeof(height));
for(int i = ; i < n; i++){
int x, y;
scanf("%d%d", &x, &y);
height[x] = y;
mmx = max(mmx, x);
mmin = min(mmin, x);
} build(, , mmx); int ans = -, st = mmin, ed = mmx;
while(st <= ed){
int mid = (st + ed) / ;
if(check(mid)){
ed = mid - ;
ans = mid;
}
else{
st = mid + ;
}
} printf("%d\n", ans);
return ;
}
好吧既然是单调队列专题,就去学习一下单调队列吧。
其实刚开始想到了如果加入了一个雨滴之后,他和队头的高度差小于前面的,并且距离差也变大了的话,那这个雨滴肯定是没用的。之后就不会了。
应该要想到的是,当我们加入了一个雨滴之后,这一段的最大值只有可能增大或不变,最小值只有可能减小或者不变。他们都是单调的。
可以用一个单调队列来维护最大最小值,队头元素是最小值,队尾元素是最大值。
先按照横坐标对雨滴排个序,然后一个个加入,当队头和队尾纵坐标之差大于等于d的时候就把队头丢掉。因为之后加入队列的那个元素和队头虽然也会满足大于等于d但是宽度就不是最小的了。
但是这样只是找到了从左到右的一个单调序列,还应该再考虑一下从右到左。其实就相当于纪要考虑从左到右递增的,也要考虑从左到右递减的。
虽然这道题数据有问题,只考虑从左到右也能AC
#include <iostream>
#include <set>
#include <cmath>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define inf 0x7f7f7f7f const int maxn = 1e5 + ;
const int maxd = 1e6 + ;
int n, d, mmx, mmin;
int height[maxd]; struct node{
int x, y;
}drop[maxn], que1[maxn], que2[maxn]; bool cmp(node a, node b)
{
return a.x < b.x;
} int main()
{
scanf("%d%d", &n, &d);
for(int i = ; i < n; i++){
scanf("%d%d", &drop[i].x, &drop[i].y);
}
sort(drop, drop + n, cmp); int tail = , head = , ans = inf;
for(int i = ; i < n; i++){
while(que1[tail].y >= drop[i].y && head <= tail)tail--;
que1[++tail] = drop[i];
//cout<<"head"<<que[head].x<<" tail"<<que[tail].x<<endl;
while(que1[tail].y - que1[head].y >= d){
ans = min(ans, que1[tail].x - que1[head].x);
head++;
}
}
//cout<<ans<<endl;
tail = ;
head = ;
for(int i = n - ; i >= ; i--){
while(que2[tail].y >= drop[i].y && head <= tail)tail--;
que2[++tail] = drop[i];
while(que2[tail].y - que2[head].y >= d){
ans = min(ans, que2[head].x - que2[tail].x);
head++;
}
} if(ans == inf){
printf("-1\n");
}
else{
printf("%d\n", ans);
}
return ;
}
洛谷P2698 花盆Flowerpot【单调队列】的更多相关文章
- P2698 [USACO12MAR]花盆Flowerpot 单调队列
https://www.luogu.org/problemnew/show/P2698 警示 用数组写双端队列的话,记得le = 1, ri = 0:le<=ri表示队列非空 题意 求一个最小的 ...
- 洛谷P1776--宝物筛选(单调队列+多重背包)
https://www.luogu.org/problemnew/show/P1776 单调队列+多重背包的讲解https://www.cnblogs.com/JoeFan/p/4165956.htm ...
- 洛谷P1886--滑动窗口(单调队列模板)
https://www.luogu.org/problemnew/show/P1886 单调队列的操作上比普通队列多了可以从尾端出队 单调队列保持队内元素单调递增/递减,以保证队首元素为最小/最大元素 ...
- [洛谷P1886]滑动窗口 (单调队列)(线段树)
---恢复内容开始--- 这是很好的一道题 题目描述: 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口. 现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的 ...
- 【洛谷】【动态规划+单调队列】P1714 切蛋糕
[题目描述:] 今天是小Z的生日,同学们为他带来了一块蛋糕.这块蛋糕是一个长方体,被用不同色彩分成了N个相同的小块,每小块都有对应的幸运值. 小Z作为寿星,自然希望吃到的第一块蛋糕的幸运值总和最大,但 ...
- 【洛谷】【动态规划+单调队列】P1725 琪露诺
[题目描述:] 在幻想乡,琪露诺是以笨蛋闻名的冰之妖精. 某一天,琪露诺又在玩速冻青蛙,就是用冰把青蛙瞬间冻起来.但是这只青蛙比以往的要聪明许多,在琪露诺来之前就已经跑到了河的对岸.于是琪露诺决定到河 ...
- [USACO12MAR]花盆Flowerpot (单调队列,二分答案)
题目链接 Solution 转化一下,就是个单调队列. 可以发现就是一段区间 \([L,R]\) 使得其高度的极差不小于 \(d\) ,同时满足 \(R-L\) 最小. 然后可以考虑二分然后再 \(O ...
- 洛谷 P1886 滑动窗口(单调队列)
题目链接 https://www.luogu.org/problemnew/show/P1886 题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始 ...
- 洛谷p2216 多次单调队列,扫描矩阵中的最大值减去最小值最的固定大小子矩阵
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int ...
随机推荐
- 阿里云被挖矿使用,导致cpu长期处于100%,ddgs进程,xWx3T进程,关于redis密码
1.使用top命令,查看到一个叫xWx3T的进程cpu占用99.8%,由于我的阿里云是单核的,所以最高只能100%. 把它用kill命令杀死后,过一会儿又启动了,又占用100%. 使用ps -ef可以 ...
- [原] unity3d调用android版 人人sdk
开发过程 遇到天坑:纯android工程没问题,集成到unity3d中 就老提示 没登陆 .最后跟到底 发现是Util.java 中 openUrl 函数出的bug.unity3d 中调android ...
- [web] spring boot 整合MyBatis
1.maven依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="h ...
- okHttp3自用封装
okHttp都已经出到3.2.0了,现在才开始要用到它,感觉自己好low~~ 根据平时自己的习惯,还是自己做一下封装,让代码撸起来更加顺畅一点! okhttp-3.2.0和okio-1.7.0就不多说 ...
- js中的string.format
String.prototype.format = function(args) { var result = this; if (arguments.length > 0) { if (arg ...
- HNOI2015题解
奇了怪了我上次发的题解怎么不见了? 题意自己戳链接-- Day 1 id=4008">HNOI2015 Arthur 思路:期望DP 直接DP是死也D不出的 转化一下 令f[i][j] ...
- Dubbo -- 系统学习 笔记 -- 示例 -- 多注册中心
Dubbo -- 系统学习 笔记 -- 目录 示例 想完整的运行起来,请参见:快速启动,这里只列出各种场景的配置方式 多注册中心 可以自行扩展注册中心,参见:注册中心扩展 (1) 多注册中心注册 比如 ...
- 诡异的DataTime.Now.ToString()
昨天晚上调程序的时候在服务器上出现这种问题 DataTime.Now.ToString("yyyy-MM-dd HH:mm:ss") 居然出现了2014-8-14 8:nn:14: ...
- NetBpm 示例:请假审批(6)
转载注明出处: http://www.cnblogs.com/anbylau2130/p/3877983.html 原文: 请假示例 流程定义包源码下载(注:par包就是zip格式压缩包).原文地址: ...
- ios开发之--解决“Could not insert new outlet connection”的问题。
在Xcode中,我们能够在StoryBoard编辑界面或者是xib编辑界面中通过“Control键+拖拽“的方式将某个界面元素和相应的代码文件连接起来.在代码文件里创建outlet. 只是.假设你的运 ...