1. 程式人生 > >hdu5289 ST表+二分

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); } }