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]
解题思路:
枚举左端点,二分查找右端点,用RMQ维护区间最大值和最小值
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <stack>
#define LL long long
using namespace std;
const int MAXN = 100000 + 10;
int A[MAXN];
int dp1[MAXN][20], dp[MAXN][20];
int N, M;
void RMQ_init_Min()
{
for(int i=0;i<N;i++) dp1[i][0] = A[i];
for(int j=1;(1<<j) <= N;j++)
{
for(int i=0;i+(1<<j) - 1 < N;i++)
{
dp1[i][j] = min(dp1[i][j-1], dp1[i + (1<<(j-1))][j-1]);
}
}
}
int RMQ_Min(int L, int R)
{
int k = 0;
while(1<<(k+1) <= R - L + 1) k++;
return min(dp1[L][k], dp1[R-(1<<k)+1][k]);
}
void RMQ_init_Max()
{
for(int i=0;i<N;i++) dp[i][0] = A[i];
for(int j=1;(1<<j) <= N;j++)
{
for(int i=0;i+(1<<j) - 1 < N;i++)
{
dp[i][j] = max(dp[i][j-1], dp[i + (1<<(j-1))][j-1]);
}
}
}
int RMQ_Max(int L, int R)
{
int k = 0;
while(1<<(k+1) <= R - L + 1) k++;
return max(dp[L][k], dp[R-(1<<k)+1][k]);
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &N, &M);
for(int i=0;i<N;i++) scanf("%d", &A[i]);
RMQ_init_Min();
RMQ_init_Max();
long long ans = 0;
for(int i=0;i<N;i++)
{
int l = i, r = N-1;
while(l <= r)
{
int mid = (l + r) >> 1;
int low = RMQ_Min(i, mid);
int high = RMQ_Max(i ,mid);
//cout << l << ' ' << r << ' ' << high << ' ' <<low << endl;
if(high - low < M) l = mid + 1;
else r = mid - 1;
}
//cout << l << endl;
ans += (l - i);
}
printf("%I64d\n", ans);
}
return 0;
}版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU 5289 Assignment(2015 多校第一场二分 + RMQ)
原文:http://blog.csdn.net/moguxiaozhe/article/details/46999155