[USACO2012-Mar-Silver] Flowerpot 题解(单调队列 c++)

USACO12MAR Flowerpot S题解(单调队列 c++)

题目链接:USACO2012-Mar-Silver Flowerpot

题意:

  • 给你n个点,每个点有对应的x,y
  • 确认是否存在两个点,在 y 1 , y 2 y_1,y_2 y1,y2满足要求的情况下,输出最小的 ∣ x 2 − x 1 ∣ \lvert x_2 - x_1 \rvert ∣x2−x1∣

思路:

  • 如果暴力的话,我们就考虑对于每一个点,寻找其对应的 ∣ y 1 − y 2 ∣ > = D \lvert y_1-y_2 \rvert >= D ∣y1−y2∣>=D 的所有点,然后找最小的 ∣ x 2 − x 1 ∣ \lvert x_2 - x_1 \rvert ∣x2−x1∣
cpp 复制代码
#include <iostream>
#include <vector>
#include <deque>
#include <algorithm>

using namespace std;

int ans = 0x3f3f3f3f;

int main() {
    int n, d;
    cin >> n >> d;
    vector<vector<int>> v(n, vector<int>(2));
    for (int i = 0; i < n; i ++)
        cin >> v[i][0] >> v[i][1];
    sort(v.begin(), v.end());
    for (int i = 0; i < n; i ++)
    {
        for (int j = i + 1; j < n; j ++) {
            if (v[j][1] - v[i][1] >= d)
                ans = min(ans, v[j][0] - v[i][0]);
        }
    }
    if (ans == 0x3f3f3f3f)
        cout << -1;
    else
        cout << ans;
    return 0;
}
  • 暴力的时间复杂度为 O ( n 2 ) O(n^2) O(n2)。
  • 不如我们这样想:首先把这些点按x坐标进行排序,令 l l l在这些点中进行遍历,对于每一个 l ∈ ( 1 , n ) l \in (1,n) l∈(1,n)我们都可以求出最小的 r r r,使得刚好在 l , r l,r l,r区间内恰好存在 ∣ y 1 − y 2 ∣ > = D \lvert y_1-y_2 \rvert >= D ∣y1−y2∣>=D的情况(区间 l , r − 1 l,r-1 l,r−1就不存在)
  • 这样问题就成了一个大小不固定的滑动窗口问题。我们使用队列q1的头结点存储从a[l].x开始y最大的值,q2存储最小值。
  • 以q1为例,若a[i+1]>a[i]则a[i]没意义的。因为当r=i时还没有满足 ∣ y 1 − y 2 ∣ > = D \lvert y_1-y_2 \rvert >= D ∣y1−y2∣>=D。若 y_{i+1}-y_j \>= D(j\= D(j\>i+1) , 我们求最小的 ,我们求最小的 ,我们求最小的\\lvert x_2 - x_1 \\rvert,所以当ai+1在时,ai永无出头之日
  • 我们通过这种方式,遍历出每一个l时l,r中符合条件的 ∣ x 2 − x 1 ∣ \lvert x_2 - x_1 \rvert ∣x2−x1∣
代码如下
cpp 复制代码
#include <iostream>
#include <algorithm>

using namespace std;

typedef pair<int, int> PII;

const int N = 1e6 + 10;

PII a[N];

// q1维护最大值(递减)  q中存储序号 
int q1[N], q2[N];
int h1 = 1, h2 = 1, t1, t2;
int ans = 0x3f3f3f3f;

int main() {
	int n, d;
	cin >> n >> d;
	for (int i = 1; i <= n; i ++)
		cin >> a[i].first >> a[i].second;
	sort(a + 1, a + 1 + n);
	
	for (int l = 1, r = 0; l <= n; l ++) {
		while (h1 <= t1 && q1[h1] < l)		h1 ++;
		while (h2 <= t2 && q2[h2] < l)		h2 ++;
		
		while (a[q1[h1]].second - a[q2[h2]].second < d && r < n) {
			r ++;
			while (h1 <= t1 && a[q1[t1]].second < a[r].second)		t1 --;
			q1[++ t1] = r;
			while (h2 <= t2 && a[q2[t2]].second > a[r].second)		t2 --;
			q2[++ t2] = r;	
		}
		
		if (a[q1[h1]].second - a[q2[h2]].second >= d)
			ans = min(ans, abs(a[q1[h1]].first - a[q2[h2]].first));
	
	}
    if (ans == 0x3f3f3f3f)
        cout << -1;
    else
        cout << ans;
	return 0;
}

这道题想了很长时间,如有讲的不清楚的地方,恳请大家批评指正

相关推荐
ShineWinsu1 小时前
对于Qt:QListWidget常见属性以及QListWidgetItem类的解析
开发语言·c++·qt·客户端·列表·qlistwidget·qlistwidgetitem
坤坤子吖1 小时前
Linux网络编程:自定义应用层协议与 JSON 序列化
linux·服务器·网络·c++·笔记·json
吴名氏.1 小时前
Java转AI Agent教程(第十二周)检索与切分
java·开发语言·人工智能·ai·ai agent
lisw052 小时前
Dayhoff的PAM替换矩阵理论评介!
线性代数·算法·矩阵
瑞雪兆丰年兮2 小时前
JavaWeb-day10-SpringBootWeb案例
java·开发语言·javaweb·web
Elastic 中国社区官方博客2 小时前
更少的位数,相同的召回率:DiskBBQ 更保守的自动校准扫描
大数据·运维·开发语言·人工智能·elasticsearch·搜索引擎
一起学安全技术2 小时前
拆大模型 03|注意力的一句话版本:不用论文讲清 Attention
深度学习·算法·语言模型·transformer
三雷科技2 小时前
第6章第4节:自定义分词器
开发语言·c#
沫璃染墨2 小时前
从零入门计算机网络系列(十八):TCP连接管理详解——从三次握手与四次挥手到TIME_WAIT机制
运维·服务器·网络·c++·网络协议·tcp/ip·tcp
Adellle3 小时前
设计模式指南 (Java 版) ㊁
java·开发语言·设计模式