题意简述
给定n,dn,dn,d,以下nnn行每行x,yx,yx,y,表示(x,y)(x,y)(x,y)上有一点。请选择一段xxx上的区间,使得这段区间内的点的yyy值最大-最小>=d>=d>=d,并且是这段区间长度最小。
数据
输入
4 5
6 3
2 4
4 10
12 15
输出
2
思路
一看就是个单调队列。前几天单调队列开窍了,趁着开窍赶快写一篇题解。
我们会发现,假设我们现在正在考虑[l,r][l,r][l,r]之内的点(离散化之后),其中[l,r][l,r][l,r]是一段满足条件的区间。现在我们要转移到[∗,r+1][*,r+1][∗,r+1]的位置,并且[∗,r+1][*,r+1][∗,r+1]也满足条件,那么我们一定要取使[l,r+1][l,r+1][l,r+1]满足条件并且[l+1,r+1][l+1,r+1][l+1,r+1]不满足条件的lll(即满足条件且离rrr最近的lll)来更新答案。至于为什么取最近。。。因为我们要区间长度最小嘛。
那么就珂以用单调队列优化了。毕竟不是所有点都要考虑的,我们只要维护一个单调不减的队列,那么第一个(Q[head]Q[head]Q[head])就是最小,最后一个(Q[tail−1]Q[tail-1]Q[tail−1])就是最大。然后我们每次加入一个点,维护好单调性。如果此时我们的队列的长度珂以继续缩小,那么就缩小,一边缩小,一边更新最小答案。最后输出答案。
代码:
#include<bits/stdc++.h>
#define N 1001000
using namespace std;
namespace Flandle_Scarlet
{
struct node
{
int x,y;
}a[N];
bool operator<(node x,node y)
{
return x.x<y.x;//按x排序
}
int n,d;
void Input()
{
scanf("%d%d",&n,&d);
for(int i=1;i<=n;++i)
{
scanf("%d%d",&a[i].x,&a[i].y);
}
sort(a+1,a+n+1);//千万要记得排序。。。
}
node Q[N];
int head,tail;
void Solve()
{
head=tail=1;//初始化队列
int ans=0x3f3f3f3f;//由于要求最小,所以答案一开始是INF
Q[tail++]=a[1];
for(int i=2;i<=n;++i)//枚举右端点
{
while(head<tail and Q[tail-1].y>a[i].y) --tail;
Q[tail++]=a[i];//加入队列
while(head<tail and Q[tail-1].y-Q[head].y>=d)
//如果区间能缩小
{
ans=min(ans,Q[tail-1].x-Q[head].x);
//更新答案
++head;
//缩小
}
}
printf("%d\n",ans==0x3f3f3f3f?-1:ans);
//记得判误解(为了这个送一次WA)
}
void Main()
{
Input();
Solve();
}
}
int main()
{
Flandle_Scarlet::Main();
return 0;
}
这是一篇关于洛谷第2698题的题解,主要讲解如何利用单调队列来解决寻找满足条件的最小区间长度的问题。题目要求在给定点集(x, y)中找到一段x上的区间,使得该区间内点的y值最大值与最小值之差大于等于d,同时区间长度最小。通过分析,作者指出可以利用单调队列的性质,不断更新满足条件的最小区间。在维护单调不减的队列过程中,不断检查是否能进一步缩小区间长度,并更新答案。最后给出实现代码。"
111219790,10297402,深度学习目标检测:从RCNN到Faster RCNN,"['深度学习', '目标检测', '卷积神经网络', 'Faster RCNN']
1920

被折叠的 条评论
为什么被折叠?



