牛客多校5 King of Range 单调队列

题目描述

Given n​ integers a1,a2,⋯ ,an   and m queries. For each query, you are given a const k​ and you should determine how many different pairs (l,r) are there meeting the condition that the range of the subsequence  al,al+1,⋯ ,ar    is strictly greater than k​.

Note: the range of a sequence equals the difference between the maximum and the minimum of the sequence.

输入描述:

The first line contains two integers n,m (1≤n≤105,1≤m≤100), denoting the number of given integers and the number of queries respectively.

The second line contains n integers a1,a2,⋯ ,an (1≤ai≤10^9)a, denoting the given integers.

Next m lines each contains one integer k (1≤k≤10^9)k\, denoting the queries.

输出描述:

Print m lines each contains one integer, denoting the answers.

示例1

输入

5 1
1 2 3 4 5
2

输出

3

说明

There are three pairs, (1,4),(1,5),(2,5)​, which meet the condition.

题意:给出一个序列,对m次询问,每次给出一个常数k,求有多少个序列满足范围大于k(范围指的是这段序列的极差(最大值-最小值)。

思路:用两个单调队列分别维护最大值和最小值;
每次固定左边界,那么只需要寻找满足条件的最小的右边界,后面的都满足,加上差值即可。

代码如下:

#include <bits/stdc++.h>
using namespace std;
#define N 100005
typedef long long ll;
int n,m,k,a[N],h1,t1,h2,t2;
int pa[N],pi[N];//分别为维护最大值的递减序列和最小值的递增队列 
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	while(m--){
		scanf("%d",&k);
		ll ans=0;
		h1=h2=1;t1=t2=0;//h1,t1为pa的头和尾,h2,t2为pi的头和尾 
		int l=1;//固定左端点 
		for(int i=1;i<=n;i++){
			while(h1<=t1&&a[pa[t1]]<=a[i]) t1--;//维护单调递减队列 
			pa[++t1]=i;
			while(h2<=t2&&a[pi[t2]]>=a[i]) t2--;//维护单调递增队列 
			pi[++t2]=i;
			while(a[pa[h1]]-a[pi[h2]]>k){//得到了以l为左端点时的满足条件的最小右端点 
				ans+=1ll*(n-i+1);//累加和,后面的都满足 
				l++;//左端点++ 
				if(l>pa[h1]) h1++;//维护pa的队首 
				if(l>pi[h2]) h2++;//维护pi的队首
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值