题意:给你一个序列,1到n。问你有几个连续子序列满足其中最大值和最小值的差小于k。
思路:这道题的方法多种,这里先写最简单也是最快的单调队列的方法。
维护两个单调队列,分别维护最大值和最小值,依次将元素放进去,因此位置p到i都之间都可以延伸到。。还是看代码吧
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<stack>
#include<math.h>
#include<string>
#include<vector>
#include<cstdio>
#include<time.h>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<string.h>
#include<algorithm>
#define ll long long
#define PI acos(-1.0)
using namespace std;
const ll MAXN=1e5+5;
ll n,k;
ll a[MAXN];
deque<ll>mx,mi;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
if(n==1){cout<<1<<endl;continue;}
if(k==0) {cout<<0<<endl;continue;}
mx.clear();
mi.clear();
ll ans=0;
ll p=1;
for(int i=1;i<=n;i++)
{
while(!mx.empty()&&mx.front()<a[i]) mx.pop_front();//将元素放入两个队列
mx.push_front(a[i]);
while(!mi.empty()&&mi.front()>a[i]) mi.pop_front();
mi.push_front(a[i]);
while(!mx.empty()&&!mi.empty()&&mx.back()-mi.back()>=k)
{
ans=ans+i-p;//p到p+1,p+2,,,i-1都可以满足
if(mx.back()==a[p]) mx.pop_back();//恰好该p元素被删除
if(mi.back()==a[p]) mi.pop_back();
p++;
}
}
while(p<=n)//还要处理p的末尾
{
ans=ans+n-p+1;
p++;
}
cout<<ans<<endl;
}
}