hdu5289 RMQ+二分
RMQ预处理最大值,最小值,然后对于每一点,二分可能满足的区间长度,长度-1就是该店开始的区间满足的个数。
#include<stdio.h> #include<string.h> #include<math.h> #define maxn 100010 #define LL __int64 int dp1[maxn][20],n,a[maxn],dp2[maxn][20]; int min(int x,int y) {return x<y?x:y;} int max(int x,int y) {return x>y?x:y;} void rmq() { int i,j; for(i=1;i<=n;i++) { dp1[i][0]=a[i]; dp2[i][0]=a[i]; } for(j=1;j<=17;j++) { for(i=1;i+(1<<j)-1<=n;i++) { dp1[i][j]=min(dp1[i][j-1],dp1[i+(1<<(j-1))][j-1]); dp2[i][j]=max(dp2[i][j-1],dp2[i+(1<<(j-1))][j-1]); } } } int ok(int m,int l,int k) { int r=l+m-1; int t=(int)(log(m*1.0)/log(2.0)); int minnum=min(dp1[l][t],dp1[r-(1<<t)+1][t]); int maxnum=max(dp2[l][t],dp2[r-(1<<t)+1][t]); if(maxnum-minnum<k) return 1; return 0; } int main() { int t,i,j,k; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&k); for(i=1;i<=n;i++) scanf("%d",&a[i]); rmq(); LL ans=0; for(i=1;i<=n;i++) { int l=1,r=n-i+1,m;//枚举长度 while(l<=r){ m=(l+r)>>1; if(ok(m,i,k)) { l=m+1; } else r=m-1; } ans+=l-1; } printf("%I64d\n",ans); } }