zoukankan      html  css  js  c++  java
  • 区间逼近 牛客寒假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;
    }

     

  • 相关阅读:
    sqlplus登录用户hang住
    ORACLE_19c用户密码登录失败的问题以及ORA-28040
    索引瘦身_oracle_11g
    Linux内存大页设置
    C++ 总体内容(2)
    C++ 总体内容(1)
    vector中erase的用法
    NGUI中的Tween的委托使用
    IOS Android支持中文与本地文件的读取写入
    Unity人工智能学习—确定性AI算法之追踪算法二
  • 原文地址:https://www.cnblogs.com/qingjiuling/p/10449708.html
Copyright © 2011-2022 走看看