链接:https://ac.nowcoder.com/acm/contest/317/G
来源:牛客网
题目描述
小a有一个长度为nn的排列。定义一段区间是"萌"的,当且仅当把区间中各个数排序后相邻元素的差为11
现在他想知道包含数x,yx,y的长度最小的"萌"区间的左右端点
现在他想知道包含数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
备注:
保证2⩽n⩽105,1⩽x,y⩽n
#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 ",l,r); } return 0; }