正题
链接
https://www.luogu.org/record/show?rid=7934370
大意
有n滴水,给出坐标,水每一个时间单位会往下掉一格,花盆可以随意摆放,要求在宽度最小的情况下接住的第一滴水和最后一滴水时间差超过D
解题思路
横坐标排序,枚举左边,然后维护移动窗口,之后递增右边直到时间差大于D,然后记录取最小值。
代码
#include<cstdio>
#include<algorithm>
using namespace std;
struct node{
int x,t;
}a[100001];
int h1,t1,h2,t2,q[100001],q2[100001];
int n,D,ans,r;
bool cmp(node x,node y)//排序
{
return x.x<y.x;
}
int main()
{
scanf("%d%d",&n,&D);
for (int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].x,&a[i].t);
}
sort(a,a+1+n,cmp);
h1=1;t1=0;ans=2147483647;
h2=1;t2=0;r=0;
for (int l=1;l<=n;l++)
{
while (h1<=t1&&q[h1]<l) h1++;
while (h2<=t2&&q2[h2]<l) h2++;//维护移动窗口
while (a[q[h1]].t-a[q2[h2]].t<D&&r<n)
{
r++;//寻找右端点
while (h1<=t1&&a[r].t>a[q[t1]].t) t1--;
while (h2<=t2&&a[r].t<a[q2[t2]].t) t2--;
//维护单调队列
q[++t1]=q2[++t2]=r;//加入队列
}
if (a[q[h1]].t-a[q2[h2]].t>=D)
ans=min(ans,a[r].x-a[l].x);//更新最小值
}
if (ans==2147483647) printf("-1");
else printf("%d",ans);
}