HDU5289
题意:求解存在最大差值小于给定K值的所有区间段。
输入:
T(测试数据)
n(数组个数)K(给定区间值的范围)
ai...(数组值)
输出:
ss(所有满足符合条件的区间段)
思路:二分+ST算法,首先利用ST算法初始化数组,找出区间段最大与最小值,然后直接二分查询数组,并判断给定区间最值是否满
足小于K的情况,所以在遍历完一次数组后,可以累加得到符合条件的所有区间和。
输入:
T(测试数据)
n(数组个数)K(给定区间值的范围)
ai...(数组值)
输出:
ss(所有满足符合条件的区间段)
思路:二分+ST算法,首先利用ST算法初始化数组,找出区间段最大与最小值,然后直接二分查询数组,并判断给定区间最值是否满
足小于K的情况,所以在遍历完一次数组后,可以累加得到符合条件的所有区间和。
#include<stdio.h> #include<string.h> #include<math.h> #include<iostream> #include<algorithm> using namespace std; const int MAXN = 100100; int i,j,n; int MIN[MAXN][20],MAX[MAXN][20]; int a[MAXN]; void build()//ST构造区间数组最值 { for(i=1; i<=n; i++) MIN[i][0]=MAX[i][0]=a[i]; for(i=1; (1<<i)<=n; i++) //按区间长度递增顺序递推 { int k = i-1; for(j=1; j+(1<<i)-1<=n; j++) //区间起点 { MIN[j][i]=min(MIN[j][k],MIN[j+(1<<k)][k]); MAX[j][i]=max(MAX[j][k],MAX[j+(1<<k)][k]); } } } int main() { int T,left,right; scanf("%d",&T); while(T--) { int k; scanf("%d%d",&n,&k); long long ss = 0; for(i=1; i<=n; i++) scanf("%d",&a[i]); build(); //初始化 int flag = 1; for(i=1; i<=n; i++) //遍历 { left=flag; right=i; while(left<=right) //二分寻找符合条件的右端点 { int mid=(left+right)/2; int x=(int)(log(double(i-mid+1))/log((double)2)); int MAXX = max(MAX[mid][x],MAX[i-(1<<x)+1][x]); int MINN = min(MIN[mid][x],MIN[i-(1<<x)+1][x]); if(MAXX-MINN>=k) left=mid+1; else right=mid-1; } flag = left; ss+=i-left; } printf("%lld\n",ss+n); } return 0; }