做法:模拟
萌区间也就是这个区间里的数是一段连续的数
做法的话是先找出题目x,y的位置,记为l,r,然后找出l,r内的最大最小值,又因为萌区间要求数是连续的,就从这段连续数最小的开始到最大的,确定缩放区间的左右端点,但现在这个缩放区间可能还包含有别的区间,我们就开始拓展拓展答案区间
主要是要注意两点,首先这个序列是个排列(所以它不会有重复数字出现),于是由这个我们可以推出一个显然的结论就是r−l=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),所以大概实际效率上是没什么大的区别的)
#includeusing 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[--mn]); qr=max(qr,pos[mn]); } } while(r!=qr){ r++;int t=a[r]; while(mx t){ ql=min(ql,pos[--mn]); qr=max(qr,pos[mn]); } } } cout< <<" "< <