题目描述
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;
}