http://acm.hdu.edu.cn/showproblem.php?pid=5289
2 4 2 3 1 2 4 10 5 0 3 4 5 2 1 6 7 8 9
5 28HintFirst Sample, the satisfied groups include:[1,1]、[2,2]、[3,3]、[4,4] 、[2,3]
/**
hdu5289||2015多校联合第一场1002贪心+RMQ
题目大意:找出连续子区间,其最大最小值只差小于k
解题思路:用rmq维护区间最大最小值只差,贪心扫一遍即可,复杂度O(nlogn)
*/
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
using namespace std;
const int N=200005;
int a[N],n,m;
int dp1[N][30];
int dp2[N][30];
void RMQ_init(int n)
{
    for(int i=1;i<=n;i++)
    {
        dp1[i][0]=a[i];
        dp2[i][0]=a[i];
    }
    for(int j=1;(1<<j)<=n;j++)
    {
        for(int i=1;i+(1<<j)-1<=n;i++)///白书上的模板,次行稍作改动,否则dp数组要扩大一倍防止RE
        {
            dp1[i][j]=max(dp1[i][j-1],dp1[i+(1<<(j-1))][j-1]);
            dp2[i][j]=min(dp2[i][j-1],dp2[i+(1<<(j-1))][j-1]);
        }
    }
}
int rmq(int x,int y)
{
    int k=0;
    while((1<<(k+1))<=y-x+1)k++;
    return max(dp1[x][k],dp1[y-(1<<k)+1][k])-min(dp2[x][k],dp2[y-(1<<k)+1][k]);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        RMQ_init(n);
        int k=1;
        long long sum=0;
        for(int i=1;i<=n;i++)
        {
            while(rmq(k,i)>=m&&k<i)k++;
            sum+=(i-k+1);
           // printf("dis i k i-k+1:%d %d %d %d\n",rmq(k,i),i,k,i-k+1);
        }
        printf("%I64d\n",sum);
    }
    return 0;
}版权声明:本文为博主原创文章,未经博主允许不得转载。
hdu5289||2015多校联合第一场1002贪心+RMQ
原文:http://blog.csdn.net/lvshubao1314/article/details/46992037