HDU5289

来源:互联网 发布:淘宝商城魅族 编辑:程序博客网 时间:2024/06/07 05:15
题意:求解存在最大差值小于给定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;}


0 0