题意:在n个数中找一共有几个数组,使得数组内的最值差不超过k,数组元素要求连续
解一:ST
#include <string.h> #include <math.h> #include <stdio.h> #define ll __int64 #define MAX(a,b) ((a)<(b)?(b):(a)) #define MIN(a,b) ((a)<(b)?(a):(b)) const int maxn=100005; ll a[maxn]; int maxx[maxn][20]; int minn[maxn][20]; void rmq(int n) //子串赋值 { int i,j; for(i=1;(1<<i)<=n;i++) for(j=1;(j+(1<<i)-1)<=n;j++) { int temp=1<<(i-1); maxx[j][i]=MAX(maxx[j][i-1],maxx[j+temp][i-1]); minn[j][i]=MIN(minn[j][i-1],minn[j+temp][i-1]); } return ; } int ask(int l,int r) { int temp=int(log(r-l+1)/log(2)); int ma=MAX(maxx[l][temp],maxx[r-(1<<temp)+1][temp]); int mi=MIN(minn[l][temp],minn[r-(1<<temp)+1][temp]); return ma-mi; } int main() { int t,n,k; ll sum; //freopen("1002.in","r",stdin); //freopen("out.out","w",stdout); while(scanf("%d",&t)!=-1) { while(t--) { sum=0; scanf("%d%d",&n,&k); for(int i=1;i<=n;i++) { scanf("%I64d",&a[i]); minn[i][0]=maxx[i][0]=a[i]; } rmq(n); for(int i=1;i<=n;i++) { int fr=i,ed=n; while(fr<ed) //二分查找 { int temp=(fr+ed)/2; if(ask(i,temp)>=k) ed=temp-1; else fr=temp+1; } if(ask(i,ed)<k) //坐标差值就是从i点为起点一共有多少个满足的子串 sum+=((ll)(ed-i+1)); else sum+=((ll)(ed-i)); } printf("%I64d\n",sum); } } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-11-08 17:11:53