[USACO12MAR]花盆Flowerpot(二分答案+單調隊列)

傳送門

題意:直接看題意即可

題解:首先可以通過二分枚舉區間大小,然後通過單調隊列求出每個區間的最大值和最小值進行比較,最後得出答案即可。

附上代碼:


#include<bits/stdc++.h>

using namespace std;

const int maxn=1e5+5;
const int maxd=1e6+5;

int n,d;
int deq[maxn],mx[maxn],mn[maxn];
int ans=0;

struct point{
    int x,y;
};
point points[maxn];

bool cmp(point a,point b)
{
    return a.x<b.x;
}

bool cal(int len)
{
    ans=0;
    int s=0,t=0;
    for(int i=0;i<n;i++){
        while(s<t&&points[deq[t-1]].y<=points[i].y){
            t--;
        }
        deq[t++]=i;
        while(points[i].x-points[deq[s]].x>len){
            s++;
        }
        mx[i]=points[deq[s]].y;
    }
    s=t=0;
    for(int i=0;i<n;i++){
        while(s<t&&points[deq[t-1]].y>=points[i].y){
            t--;
        }
        deq[t++]=i;
        while(points[i].x-points[deq[s]].x>len){
            s++;
        }
        mn[i]=points[deq[s]].y;
    }
//    cout<<len<<" "<<endl;
//    for(int i=0;i<n;i++){
//        cout<<mx[i]<<" ";
//    }
//    cout<<endl;
//    for(int i=0;i<n;i++){
//        cout<<mn[i]<<" ";
//    }
//    cout<<endl;
    for(int i=0;i<n;i++){
        ans=max(ans,mx[i]-mn[i]);
    }
    if(ans>=d){
        return true;
    }else{
        return false;
    }
}

int main()
{
    scanf("%d%d",&n,&d);
    for(int i=0;i<n;i++){
        point &e=points[i];
        scanf("%d%d",&e.x,&e.y);
    }
    sort(points,points+n,cmp);
    int lb=-1,ub=maxd;
    while(ub-lb>1){
        int mid=(lb+ub)>>1;
        if(cal(mid)){
            ub=mid;
        }else{
            lb=mid;
        }
    }
    if(ub>1e6){
        printf("%d\n",-1);
    }else{
        printf("%d\n",ub);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章