标签:
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