/*
rmq模版
*/
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int MAXN = 100100;
int n,query;
int A[MAXN];
int FMin[MAXN][20],FMax[MAXN][20];
void Init()
{
int i,j;
for(i=1; i<=n; i++)
FMin[i][0]=FMax[i][0]=A[i];
for(i=1; (1<<i)<=n; i++) //按区间长度递增顺序递推
{
for(j=1; j+(1<<i)-1<=n; j++) //区间起点
{
FMin[j][i]=min(FMin[j][i-1],FMin[j+(1<<(i-1))][i-1]);
FMax[j][i]=max(FMax[j][i-1],FMax[j+(1<<(i-1))][i-1]);
}
}
}
int Querymax(int l,int r)//区间最大
{
int k=(int)(log(double(r-l+1))/log((double)2));
return max(FMax[l][k],FMax[r-(1<<k)+1][k]);
}
int Querymin(int l,int r)//区间最小
{
int k=(int)(log(double(r-l+1))/log((double)2));
return min(FMin[l][k],FMin[r-(1<<k)+1][k]);
}
int main()
{
int i,a,k,t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
for(i=1; i<=n; i++)
scanf("%d",&A[i]);
Init();
__int64 ans=0;
int map=2;
for(i=1; i<=n; i++)///枚举左端点 二分右端点
{
int left=map;
int right=n;
while(left<=right)
{
int mid=(left+right)/2;
int maxx=Querymax(i,mid);
int minn=Querymin(i,mid);
if(maxx-minn<k)
{
map=mid+1;
left=mid+1;
}
else
right=mid-1;
}
// printf("%d %d\n",i,left-1);
ans+=(left-1)-i+1;
}
printf("%I64d\n",ans);
}
return 0;
}
hdu 5289 Assignment (rmq模版)
最新推荐文章于 2020-07-28 17:32:20 发布