题意:
给定一个数组
和一个整数
,问有多少个连续区间的最大值和最小值的差不大于
思路:
首先对于固定起点的连续区间,随着终点的增大,其区间最大值一定非递减,区间最小值一定非递增,故区间最大值和最小值的差一定是非递减的。
故可以利用双指针来快速求出合法区间的个数。
但该过程还需要快速求出区间最小值和最大值,故使用双端队列来实现滑动窗口。
保持队列的单调性,同时维护队首元素始终有效。
此题得解。
代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
#define lson rt<<1
#define rson rt<<1|1
const int INF = 1e9 + 7;
const int A = 1e5 + 10;
int N,K,a[A];
int que_Mx[A], que_Mn[A];
int Ln,Rn,Lx,Rx;
int main(){
scanf("%d%d",&N,&K);
for(int i = 1; i <= N; i++){
scanf("%d",&a[i]);
}
int st = 1,ed = 1;
Ln = Rn = Lx = Rx = 0;
ll ans = 0;
while(st<=N){
while(ed <= N){
while(Ln < Rn && a[que_Mn[Rn]] >= a[ed]) Rn--;
while(Lx < Rx && a[que_Mx[Rx]] <= a[ed]) Rx--;
que_Mn[++Rn] = que_Mx[++Rx] = ed;
if(a[que_Mx[Lx+1]] - a[que_Mn[Ln+1]] > K) break;
ed++;
}
ans += 1LL*(ed - st);
if(que_Mx[Lx+1] == st) Lx++;
if(que_Mn[Ln+1] == st) Ln++;
st++;
}
printf("%I64d\n",ans);
return 0;
}