HDU5289 Assignment

来源:互联网 发布:淘宝优惠券那个网站好 编辑:程序博客网 时间:2024/05/22 05:25

题目大意:问数组a中,区间[i,j]中最大值和最小值之差不超过k,问这样的区间有多少个。

思路:预处理出区间[i,j]中的最大值最小值(这里用的是ST算法,也有用线段树的),然后枚举左端点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 200005const double PI = acos(-1.0);using namespace std;int a[N];int mx[N][21], mi[N][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;}


0 0
原创粉丝点击