第3次训练的H题解

[USACO 2012 Mar S]Flowerpot

https://ac.nowcoder.com/acm/problem/24325

题目:[USACO 2012 Mar S]Flowerpo

题目大意:给定N个雨滴的位置(1 <= N <= 100,000),每个雨滴在二维平面上落下,其中y表示雨滴的垂直高度,x表示其在一维数轴上的位置。每个雨滴以每秒1个单位的速度向下落(朝向x轴)。现在需要在x轴上放置一个宽度为W的花盆,使得第一个落在花盆里的雨滴和最后一个落在花盆里的雨滴之间的时间差至少为D(以便花盆里的植物能够得到充足的水分)。如果一个水滴恰好落在花盆的边缘上,则计为落在花盆内。给定D和N个雨滴的位置,请计算W的最小可能值。

话说看到最大最小,我的第一印象就是二分了

训魔怔了()

由于落下的雨滴速度匀速且速度为1(反现实雨滴)那么高度就是落下的时间

首先我们先按雨滴给的x轴进行排序,至于接雨滴部分,其实我们只要花盆里最先落下的雨滴和最晚落下的雨滴就可以啦,维护一个固定长度,会移动的区间,我们可以很自然的想到滑动窗口,但由于给的专题训练是队列,(话说单调队列不也是队列,不是),那么我们就可以用堆去快速的找最大最小值 (决不是想偷懒)

那么在存的时候就是要存两个东西了,雨滴落下的时间以及雨滴x坐标

第一部分 二分板

int l = 1 , r = 1e6;
	while(l < r){
		int mid = (l + r) >> 1;
		if(check(mid)) r = mid;
		else  l = mid + 1;
		//cout << l << " "   << r << "\n";
	}
	if(l >= 1e6) cout << -1 << "\n";
	else cout << l  << "\n";

第二部分

bool check(int x){
	priority_queue<pair<int ,int > , vector<pair<int , int >>,greater<pair<int , int >>> q;
	priority_queue<pair<int ,int > ,vector<pair<int , int >> ,less<pair<int , int >>> p;
	for(int i =  1 ; i <= n ; i ++){
		p.push({a[i].second,a[i].first});
		q.push({a[i].second,a[i].first});
		while(!p.empty() && p.top().second + x < a[i].first  ) p.pop();
		while(!q.empty() && q.top().second + x < a[i].first  ) q.pop();
		if(!q.empty() && p.top().first - q.top().first >= d) return true;
	}
	return false;
}

那么我们就好好看一下check部分 ,首先先开一个大根堆和小根堆,毕竟要找最大和最小, 其实滑动窗口的左边界不就是雨滴的x坐标吗,那么一开始我们这个滑动窗口的覆盖范围不就是a[i].first 到 a[i].first + x 吗

		while(!p.empty() && p.top().second + x < a[i].first  ) p.pop();
		while(!q.empty() && q.top().second + x < a[i].first  ) q.pop();

这两部分不就是模拟滑动窗口元素弹出,建议结合滑动窗口理解

完成ac代码就是

#include<iostream>
#include<vector>
#include<queue>
#include<algorithm> 
using namespace std;
const int N = 1e5 + 10;
pair<int ,int >a[N];
int n , d;
bool check(int x){
	priority_queue<pair<int ,int > , vector<pair<int , int >>,greater<pair<int , int >>> q;
	priority_queue<pair<int ,int > ,vector<pair<int , int >> ,less<pair<int , int >>> p;
	for(int i =  1 ; i <= n ; i ++){
		p.push({a[i].second,a[i].first});
		q.push({a[i].second,a[i].first});
		while(!p.empty() && p.top().second + x < a[i].first  ) p.pop();
		while(!q.empty() && q.top().second + x < a[i].first  ) q.pop();
		if(!q.empty() && p.top().first - q.top().first >= d) return true;
	}
	return false;
}
int main(){
	
	cin >> n >> d;
	
	for(int i = 1 ; i <= n ; i ++){
		cin >> a[i].first >> a[i].second;
	}
	sort(a + 1 , a + 1 + n);
	int l = 1 , r = 1e6;
	while(l < r){
		int mid = (l + r) >> 1;
		if(check(mid)) r = mid;
		else  l = mid + 1;
		//cout << l << " "   << r << "\n";
	}
	if(l >= 1e6) cout << -1 << "\n";
	else cout << l  << "\n";
}
全部评论

相关推荐

2025-12-06 01:10
已编辑
哈尔滨工程大学 Java
一面问的真细,二面不知为啥变双机位。9.29快手主站平时怎么学习&nbsp;AI&nbsp;的,国内外知名大模型,实习公司都用的什么大模型,怎么评估效果的java池化思想,线程池构造方法的核心参数,线程池中阻塞队列注意事项,submit方法参数和执行逻辑,shutdown和shutdownnow,核心线程允许过期吗threadlocal底层,为什么key是弱引用,key回收了再get或者set这个value会怎样aqs,如何保证公平性java代理java堆划分,新生代还有别的晋升老年代的情况吗,什么时候触发gc,gc失败抛什么异常,如何排查oom,导出dump命令redis数据结构,哪个底层是跳表,和其他数据结构对比布隆过滤器会出现大key问题吗,你咋实现的布隆过滤器你怎么实现redis分布式锁,可重入,续期聚簇索引非聚簇索引select语句会加锁吗,怎么实现的不加锁undolog&nbsp;redolog&nbsp;binlog怎么能让select加锁,update这个范围加的什么锁,update一条呢手撕简单01背包,接雨水10.10快手主站意图识别用的哪个大模型,走到意图和rag的比例,faq是点击的吗自然语言怎么识别的gap一年干啥了,转正怎么样没跟组里提意向吗,研究生研究方向是传统算法吗,会大模型微调吗注册场景为什么用布隆过滤器,原理分布式锁底层的key怎么拼的,value里是什么redis持久化zset底层mysql索引结构,一个表三个字段有主键唯一索引和没索引的字段会有几个b+树,聚簇索引非聚簇索引存的啥无手撕
点赞 评论 收藏
分享
评论
4
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务