luogu-单调队列/单调栈专题

大兔子大兔子 提交于 2019-12-05 09:53:24

P2698 [USACO12MAR]花盆Flowerpot

题意:

给出水滴的坐标与下落时间,你需要构造一个盆,使他的宽度满足
在其范围内能够接住水滴时间(第一滴和最后一滴/最大与最小值)时间差大于等于k,且使得这个盆的直径最小

思路:

会想到尺取法(双指针)来在符合条件内缩小范围,同时又涉及到区间最值问题,那么上来想就很容易想到单调队列或者单调栈来维护区间最值
两点:满足区间最小与最大之差大于k,且使得其长度最小。
(1)区间最值:由于是要进行双指针操作:所以选择双端队列来实现单调队列维护最值,且能维护在 q.front().x ~ q.back().x的区间最值

(2)在符合条件下对 front/队首进行移动,以达到缩小区间操作

code:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
const int inf = 0x3f3f3f3f;
struct node{
    int x,y;
};
bool cmp(node a,node b){
    return a.x<b.x;
}
node arr[maxn];
deque<node>q1;
deque<node>q2;
int main(){
    int n,k;
    cin>>n>>k;
    for(int i=0;i<n;i++){
        cin>>arr[i].x>>arr[i].y;
    }
    sort(arr,arr+n,cmp);
    int ans = inf;
    for(int i=0;i<n;i++){
        node tmp;
        //维护最大最小单调队列
        while(!q1.empty()&&q1.back().y<arr[i].y) q1.pop_back();
        tmp = arr[i];
        q1.push_back(tmp);
        while(!q2.empty()&&q2.back().y>arr[i].y) q2.pop_back();
        q2.push_back(tmp);
        while(!q1.empty()&&!q2.empty()&&q1.front().y-q2.front().y>=k){
            node pos;
            if(q1.front().x<q2.front().x) {pos = q1.front(); q1.pop_front();}
            else {pos = q2.front(); q2.pop_front();}
            ans = min(ans,arr[i].x-pos.x);
        }
    }
    if(ans!=inf) cout<<ans<<endl;
    else cout<<-1<<endl;
}
View Code

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!