CF1817A的题解

(一)

先找出符合 \(a_i \ge a_{i+1} \ge a_{i+2}\) 的所有 \(i\)

将问题按左端点(或右端点)排序。

对于每一个问题,找出最左的符合条件的 \(l\) 和最右的符合条件的 \(r\)

由于时间会超,\(r\) 用二分搜。

然后一般的 \(ans\) 就是给定区间长度减去 \(r\)\(l\) 间距离。

特殊情况见代码。

(二)

AC 代码。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,q,l,a[200011],k,ans[200011],be[200011];
struct node{
	int x,y;
}dis[200011];
struct nodd{
	int x,y,sit;
}ask[200011];
bool cmp(nodd p1,nodd p2){
	return p1.x<p2.x||p1.x==p2.x&&p1.y<p2.y;
}
signed main(){
	scanf("%lld%lld",&n,&q);
	for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
	for(int i=1;i<=n-2;i++)if(a[i]>=a[i+1]&&a[i+1]>=a[i+2])be[++k]=i;
	be[k+1]=1000000;
	for(int i=1;i<=q;i++){
		scanf("%lld%lld",&ask[i].x,&ask[i].y);
		ask[i].sit=i;
	}
	sort(ask+1,ask+q+1,cmp);
	for(int i=1;i<=q;i++){
		while(be[l]<ask[i].x&&l<k)l++;
		int ll=l,rr=k,r;
		while(ll<=rr){
			int mid=(ll+rr)>>1;
			if(be[mid]+2<=ask[i].y)r=mid,ll=mid+1;
			else rr=mid-1;
		}
		if(be[l]+2>ask[i].y||be[l]<ask[i].x)ans[ask[i].sit]=ask[i].y-ask[i].x+1;
		else ans[ask[i].sit]=ask[i].y-ask[i].x+1-(r-l+1);
	}
	for(int i=1;i<=q;i++)printf("%lld\n",ans[i]);
	return 0;
}
posted @ 2024-03-28 08:22  Jerry_heng  阅读(20)  评论(0)    收藏  举报