小a的排列

链接:https://ac.nowcoder.com/acm/contest/317/G
来源:牛客网

题目描述

小a有一个长度为nn的排列。定义一段区间是"萌"的,当且仅当把区间中各个数排序后相邻元素的差为11
现在他想知道包含数x,yx,y的长度最小的"萌"区间的左右端点
也就是说,我们需要找到长度最小的区间[l,r][l,r],满足区间[l,r][l,r]是"萌"的,且同时包含数xx和数yy
如果有多个合法的区间,输出左端点最靠左的方案。


输入描述:

第一行三个整数N,x,yN,x,y,分别表示序列长度,询问的两个数
第二行有nn个整数表示序列内的元素,保证输入为一个排列

输出描述:

输出两个整数,表示长度最小"萌"区间的左右端点
示例1

输入

5 2 3
5 2 1 3 4

输出

2 4

说明

区间[2,4]={2,1,3}[2,4]={2,1,3}包含了2,32,3且为“萌”区间,可以证明没有比这更优的方案
示例2

输入

8 3 5
6 7 1 8 5 2 4 3

输出

5 8

备注:

保证2n105,1x,yn
#include<bits/stdc++.h>
#include<stack>
using namespace std;
typedef long long ll;
 
int n,x,y,maxx,minn,l,r;
int a[100005];//原数组
int b[100005];//下标数组
 
int main()
{
    while(scanf("%d%d%d",&n,&x,&y)!=EOF)
    {
        maxx=-1;minn=111111;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            b[ a[i] ]=i;
        }
        if(b[x]>b[y])
            swap(b[x],b[y]);
        l=b[x];
        r=b[y];//x和y的左右区间
        for(int i=b[x];i<=b[y];i++)//找x到y之间的最大最小值
        {
            maxx=max(maxx,a[i]);
            minn=min(minn,a[i]);
        }
        for(int i=minn;i<=maxx;i++)//找哪些数的下标不在这个范围内
        {//最小到最大之间的数不在区间里,就要扩大区间
            int temp=minn;
            if( b[i]<l )//向左扩,同时跟新最大最小值
            {
                for(int j=b[i];j<=l;j++)
                {
                    maxx=max(maxx,a[j]);
                    minn=min(minn,a[j]);
                }
                l=b[i];
                if(temp!=minn)
                    i=minn;
            }
            else if(b[i]>r)//向右扩
            {
                for(int j=r;j<=b[i];j++)
                {
                    maxx=max(maxx,a[j]);
                    minn=min(minn,a[j]);
                }
                r=b[i];
                if(temp!=minn)
                    i=minn;///有更新才需要重新找
            }
        }
        printf("%d %d\n",l,r);
    }
    return 0;
}

 

 
posted @ 2019-01-26 00:46  守林鸟  阅读(484)  评论(0编辑  收藏  举报