hdu 5289 Assignment(ST表+双指针)

来源:互联网 发布:常州科教城淘宝装修 编辑:程序博客网 时间:2024/06/06 08:55

题意:

给一个整数序列,多达10万个。问:有多少个区间满足“区间最大元素与最小元素之差不超过k“

解析:

如果用穷举法,有O(n2)复杂度,这肯定是不可取的。
所以可以用ST算法先预处理每个区间最大和最小值,O(nlog(n))
注意一个区间固定起点,延长终点,那么这个区间的最大值和最小值的差肯定是单调递增的。
所以这题用双指针的方法,枚举右指针rp,用左指针lp向前移动,求出满足rmq(lp,rp)<k,且lprp最大的区间,统计ans+=(rplp+1)。因为在[lp,rp]这个区间是满足要求的,那么以 rp 为结尾的,[lp,rp][lp+1,rp][rp1,rp][rp,rp]就都是满足要求的,刚好(rplp+1)个。

my code

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef __int64 ll;const int N = 100005;int A[N];int n, K;int maxv[N*2][20], minv[N*2][20];void rmq_init() {    for(int i = 1; i <= n; i++) {        maxv[i][0] = minv[i][0] = A[i];    }    for(int j = 1; (1<<j) <= n; j++) {        for(int i = 1; i + (1<<j) - 1 <= n; i++) {            maxv[i][j] = max(maxv[i][j-1], maxv[i + (1<<(j-1))][j-1]);            minv[i][j] = min(minv[i][j-1], minv[i + (1<<(j-1))][j-1]);        }    }}int rmq(int L, int R) {    int len = R - L + 1, k = 0;    while(1 << (k+1) <= len) k++;    int Max = max(maxv[L][k], maxv[R-(1<<k)+1][k]);    int Min = min(minv[L][k], minv[R-(1<<k)+1][k]);    return Max - Min;}int main() {    int T;    scanf("%d", &T);    while(T--) {        scanf("%d%d", &n, &K);        for(int i = 1; i <= n; i++) {            scanf("%d", &A[i]);        }        rmq_init();        int lp = 1;        ll ans = 0;        for(int rp = 1; rp <= n; rp++) {            while(rmq(lp, rp) >= K && lp < rp) lp++;            ans += (rp - lp + 1);        }        printf("%I64d\n", ans);    }    return 0;}
0 0
原创粉丝点击