题意:在n个数中找一共有几个数组,使得数组内的最值差不超过k,数组元素要求连续
解一:ST
#include <string.h>
#include <math.h>
#include <stdio.h>
#define ll __int64
#define MAX(a,b) ((a)<(b)?(b):(a))
#define MIN(a,b) ((a)<(b)?(a):(b))
const int maxn=100005;
ll a[maxn];
int maxx[maxn][20];
int minn[maxn][20];
void rmq(int n) //子串赋值
{
int i,j;
for(i=1;(1<<i)<=n;i++)
for(j=1;(j+(1<<i)-1)<=n;j++)
{
int temp=1<<(i-1);
maxx[j][i]=MAX(maxx[j][i-1],maxx[j+temp][i-1]);
minn[j][i]=MIN(minn[j][i-1],minn[j+temp][i-1]);
}
return ;
}
int ask(int l,int r)
{
int temp=int(log(r-l+1)/log(2));
int ma=MAX(maxx[l][temp],maxx[r-(1<<temp)+1][temp]);
int mi=MIN(minn[l][temp],minn[r-(1<<temp)+1][temp]);
return ma-mi;
}
int main()
{
int t,n,k;
ll sum;
//freopen("1002.in","r",stdin);
//freopen("out.out","w",stdout);
while(scanf("%d",&t)!=-1)
{
while(t--)
{
sum=0;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%I64d",&a[i]);
minn[i][0]=maxx[i][0]=a[i];
}
rmq(n);
for(int i=1;i<=n;i++)
{
int fr=i,ed=n;
while(fr<ed) //二分查找
{
int temp=(fr+ed)/2;
if(ask(i,temp)>=k)
ed=temp-1;
else
fr=temp+1;
}
if(ask(i,ed)<k) //坐标差值就是从i点为起点一共有多少个满足的子串
sum+=((ll)(ed-i+1));
else
sum+=((ll)(ed-i));
}
printf("%I64d\n",sum);
}
}
return 0;
}