题解:CF279C Ladder
题目传送门
题目大意
给出一个数列,每次询问一段区间
思路
注意到,题目中的山峰是不一定要单调递增和递减的,是先不降后不增的,即平地也属于山峰。我们考虑两种情况,第一种 pre 来记录前 nxt 来记录后
显然,对于一段区间,如果存在一个数,使得从左端点到它,没有情况一,并且从它到右端点,没有情况二,那么这个区间就是山峰,反之则不是。注意到,这个点我们可以二分查找,二分时分四种情况,第一种是左边有情况一,右边有情况二,那么这个区间一定不是山峰;第二种左边有情况一,右边没有情况二,那么
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1010101;
ll n,m,a[N],pre[N],nxt[N],l,r;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++){
if(a[i-1]>a[i])pre[i]++;
pre[i]+=pre[i-1];
}
for(int i=n;i>=1;i--){
if(a[i]<a[i+1])nxt[i]++;
nxt[i]+=nxt[i+1];
}
for(int i=1;i<=m;i++){
cin>>l>>r;
ll x=l,y=r,flag=0;
while(l<=r){
ll mid=l+r>>1;
if(pre[mid]-pre[x]==0&&nxt[mid]-nxt[y]==0){
flag=0;
break;
}
if(pre[mid]-pre[x]>0&&nxt[mid]-nxt[y]>0){
flag=1;
break;
}
else if(pre[mid]-pre[x]>0)r=mid-1;
else if(nxt[mid]-nxt[y]>0)l=mid+1;
}
if(!flag)cout<<"Yes"<<"\n";
else cout<<"No"<<"\n";
}
return 0;
}