用裸的St表+暴力枚举查询时稳TLE的,可以枚举每个区间的起点+二分满足条件的区间右端,这样复杂度是O(nlogn)
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; #define maxn 100005 #define ll long long int T,n,k,a[maxn],mx[maxn][30],mi[maxn][30]; ll ans; void ST(){ ans=0; for(int i=1;i<=n;i++) mx[i][0]=mi[i][0]=a[i]; for(int j=1;(1<<j)<=n;j++) for(int i=1;i+(1<<j)-1<=n;i++){ mx[i][j]=max(mx[i][j-1],mx[i+(1<<(j-1))][j-1]); mi[i][j]=min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]); } } int query(int L,int R){ int kk=log2(R-L+1); int tmp1=max(mx[L][kk],mx[R-(1<<kk)+1][kk]); int tmp2=min(mi[L][kk],mi[R-(1<<kk)+1][kk]); // cout << tmp1 << " " <<tmp2 <<' '; return tmp1-tmp2; } int main(){ cin >> T; while(T--){ scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",&a[i]); ST(); for(int i=1;i<=n;i++){ int l=i,r=n,res=0; while(l<=r){ int mid=l+r>>1; int tmp=query(i,mid); if(tmp<k) res=mid,l=mid+1; else r=mid-1; } ans+=l-i; } printf("%lld ",ans); } }