HDU 3530 Subsequence(区间最值差>=m且<=k的最大长度、双单调队列)

来源:互联网 发布:淘宝店铺信用卡套现 编辑:程序博客网 时间:2024/05/17 23:23

题目链接:
HDU 3530 Subsequence
题意:
给一个长度为n的数组,求最大的区间长度,并且这个区间满足最大值与最小值之差diff[m,k],即大于等于m,小于等于k.
数据范围:n105,m,k[0,106]
分析:
因为是在做单调队列的题,所以往单调队列上想可能容易点。
首先我们考虑以data[i]结尾的最长的满足条件的区间。因为我们需要考虑区间最大值和区间最小值,不妨维护两个单调队列:单调非递增队列dec和单调非递减队列inc,用data[i]的大小和队列尾的元素大小比较来维护队列的单调性。我们想要寻找的区间一定要满足最大值减去最小值之差diffk,所以我们同时也要调整队列首。但是我们要不要根据diffm,来调整队列首呢?实际上是不需要的,而且调整是错误的。因为尽管我们当前两个队列的差值diff<m,那必然是因为最大值太小或者最小值太大,但是我们可以通过后面的值比较大来提升最大值或者后面的值比较小来减小最小值使得diffm,如果调整当前diff使其diffm的话,相当于减少了区间长度,甚至最终会无解,越界什么的。m的正确作用应当是来判断当前两个队列中的元素能否形成满足题意的区间,如果可以的话就更新ans
时间复杂度:O(n)

#include <stdio.h>#include <string.h>#include <algorithm>#include <math.h>#include <climits>using namespace std;const int MAX_N = 100010;int n, m, k, head_dec, tail_dec, head_inc, tail_inc;int dec[MAX_N], inc[MAX_N], data[MAX_N];int main(){    while (~scanf("%d%d%d", &n, &m, &k)) {        head_dec = tail_dec = head_inc = tail_dec = 0;        for (int i = 0; i < n; ++i) {            scanf("%d", &data[i]);        }        if(m > k) {            printf("0\n");            continue;        }        memset(dec, 0, sizeof(dec));        memset(inc, 0, sizeof(inc));        int ans = 0, diff, pre = 0;        for (int i = 0; i < n; ++i) {            while (head_inc != tail_inc && data[i] < data[inc[tail_inc - 1]]) --tail_inc;            inc[tail_inc++] = i;            while (head_dec != tail_dec && data[i] > data[dec[tail_dec - 1]]) --tail_dec;            dec[tail_dec++] = i;            while(1) {                diff = data[dec[head_dec]] - data[inc[head_inc]];                if (diff > k) {                    if (dec[head_dec] < inc[head_inc]) {                        pre = dec[head_dec] + 1;                        head_dec++;                    } else {                        pre = inc[head_inc] + 1;                        head_inc++;                        }                } else break;            }            diff = data[dec[head_dec]] - data[inc[head_inc]];            if(diff >= m) ans = max(ans, i - pre + 1);//            printf("i = %d head_dec = %d head_inc = %d ans = %d\n", i, dec[head_dec], inc[head_inc], ans);//            printf("Max = %d Min = %d\n", data[dec[head_dec]], data[inc[head_inc]]);        }        printf("%d\n", ans);    }    return 0;}
0 0
原创粉丝点击