您的位置:首页 > 其它

hdu5289 Assignment

2016-06-12 23:53 267 查看
题意:给你n个数和一个数k,求存在多少个区间,区间内最大值减最小值小于k 。n
≤ 100000; a[i], k ≤ 10^9

思路:预处理出区间[i,j]中的最大值最小值,然后枚举左端点l,二分出符合条件的右端点r,以l为左端点,j为右端点(l<=j<=r)的符合条件的集合为(r-l+1)。

代码:

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<vector>
#include<cmath>
#include<ctime>
#define N 100005
#define LL long long
#define mod 1000000007
#define esp 1e-6
#define y1 y1234
#define INF 0x3f3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define maxn 200005
const double PI = acos(-1.0);
using namespace std;

int a
;
int mx
[21], mi
[21];
int n, k;

void RMQ(){
for (int j = 1; (1<<j) <= n; j++){
for (int i = 1; i + (1<<j)-1 <= n; i++){
int p = 1 << (j - 1);
mx[i][j] = max(mx[i][j - 1], mx[i + p][j - 1]);
mi[i][j] = min(mi[i][j - 1], mi[i + p][j - 1]);
}
}
}

int q(int i, int j){
int k = log2(j - i + 1.0);
int mma = max(mx[i][k], mx[j - (1 << k) + 1][k]);
int mmi = min(mi[i][k], mi[j - (1 << k) + 1][k]);
return mma - mmi;
}

int main(){
int t;
cin >> t;
while (t--){
cin >> n >> k;
for (int i = 1; i <= n; i++){
scanf("%d", &a[i]);
mx[i][0] = mi[i][0] = a[i];
}
RMQ();
LL ans = 0;
for (int i = 1; i <= n; i++){
int l = i, r = n;
while (l + 1 < r){
int m = (l + r) >> 1;
if (q(i, m) < k)l = m;
else r = m;
}
if (q(i, r) < k)
ans += (r * 1LL - i + 1);
else ans += (l * 1LL - i + 1);
}
cout << ans << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: