hdu5289 ST表+二分

用裸的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 <<'\n'; 
    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\n",ans);
    }
}

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/10022098.html