2 4 2 3 1 2 4 10 5 0 3 4 5 2 1 6 7 8 9
5 28HintFirst Sample, the satisfied groups include:[1,1]、[2,2]、[3,3]、[4,4] 、[2,3]
找一段区间 区间最大值与最小值只差小于k 共有几段区间
对于一个长度为 L 的区间 , 其子区间总数为 L*(L+1)/2
#include<iostream> #include<cstdio> #include<cstring> using namespace std; long long A[100100]; int a[100100]; int Min,Max; int st; int t; int n,k; const int Mod=1e9+7; int main() { scanf("%d",&t); A[1]=1; A[0]=0; for(int i=2;i<=100000;i++) { long long j=i; A[i]=(j+1)*j/2; } while(t--) { scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",&a[i]); Min=a[1]; Max=a[1]; st=1; long long ans=0; for(int i=2;i<=n;i++) { if(Max-a[i]>=k||a[i]-Max>=k||Min-a[i]>=k||a[i]-Min>=k) { long long sum=0; sum+=A[i-st]; //上一区间的分组总数 Max=a[i]; Min=a[i]; for(int j=i;j>0;j--) //找左起点 { if(Max-a[j]>=k||a[j]-Max>=k||Min-a[j]>=k||a[j]-Min>=k) break; Max=max(a[j],Max); Min=min(a[j],Min); st=j; } sum-=A[i-st]; //减掉重复部分 ans+=sum; continue ; } Max=max(a[i],Max); Min=min(a[i],Min); } ans+=A[n-st+1]; printf("%lld\n",ans); } }