区间逼近 牛客寒假1 小a的排列

做法:模拟

萌区间也就是这个区间里的数是一段连续的数

做法的话是先找出题目x,y的位置,记为l,r,然后找出l,r内的最大最小值,又因为萌区间要求数是连续的,就从这段连续数最小的开始到最大的,确定缩放区间的左右端点,但现在这个缩放区间可能还包含有别的区间,我们就开始拓展拓展答案区间

主要是要注意两点,首先这个序列是个排列所以它不会有重复数字出现),于是由这个我们可以推出一个显然的结论就是rl=max[l,r]min[l,r]r−l=max[l,r]−min[l,r]时这是个连续区间。

然后我们处理出每个数字出现的位置,于是可以求出第一个可能满足题目要求的区间,记为[ql,qr][ql,qr],并保存这个区间的最大最小值。

(为什么是可能呢?因为你现在只求出了x到y之间的数所需要的最短的区间,但是你并不知道这个区间里有没有其他不应该有的数字,让这个区间变得真正合法,就是我们下面要做的事情)

设每个数出现的位置为pospos。

我们可以将原始区间记为[l,r][l,r](即一开始的[pos[x],pos[y]][pos[x],pos[y]])。

尝试不断拓展这个区间[l,r][l,r],在拓展过程中如果出现了大于最大值,或者小于最小值的,就用一开始处理[ql,qr][ql,qr]的方法更新[ql,qr][ql,qr]。直至两区间重合。那么此时的[l,r][l,r]即为答案了。

这样做是O(n)O(n)的,不过常数可能稍大,因为会有重复访问。

写了RMQ的话就可以稳定O(n)O(n)了(不过预处理要O(nlogn)O(nlogn),所以大概实际效率上是没什么大的区别的)

#include <bits/stdc++.h>
using namespace std;
const int inf=1<<30;
typedef long long ll;
const double pi=acos(-1);
const int mod=1e9+7;
const int maxn=1e5+7;
int a[maxn],pos[maxn];
int main(){
    int n,x,y;scanf("%d%d%d",&n,&x,&y);int mx=0,mn=n;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        pos[a[i]]=i;
    }
    int ql=n,qr=1,l=pos[x],r=pos[y];
    if(l>r) swap(l,r);//这点特别容易错,要当心
    for(int i=l;i<=r;i++){//这个是找出了当前区间最大最小值 
        mx=max(mx,a[i]);
        mn=min(mn,a[i]);
    }
    for(int i=mn;i<=mx;i++){//这个是找出了当前区间左右端点 
        ql=min(ql,pos[i]);
        qr=max(qr,pos[i]);
    }
    //此时找出的左右端点一定不小于我们要找的答案,其中可能会包含有其他数 
    while(l!=ql || r!=qr){
        while(l!=ql){
            l--;int t=a[l];
            while(mx<t){
                ql=min(ql,pos[++mx]);
                qr=max(qr,pos[mx]);
            }
            while(mn>t){
                ql=min(ql,pos[--mn]);
                qr=max(qr,pos[mn]);
            }
        }
        while(r!=qr){
            r++;int t=a[r];
            while(mx<t){
                ql=min(ql,pos[++mx]);
                qr=max(qr,pos[mx]);
            }
            while(mn>t){
                ql=min(ql,pos[--mn]);
                qr=max(qr,pos[mn]);
            }
        }
    }
    cout<<l<<" "<<r<<endl;
    return 0;
}

 

 

posted @ 2019-02-28 13:07  清酒令  阅读(158)  评论(0编辑  收藏  举报