hdu3530 Subsequence 单调队列

//    hdu3530 Subsequence 单调队列
//    题目大意:找到一个最大的子串,使得子串区间内最大值和最小值的差
//    在low和up范围内,串的规模10w。

//    解题思路:

//    单调队列,单调队列可以保留i位置之前的最大值和最小值的下标,有了这些
//    则,每次我们比较两个队列的队头,看差值是否大于up,(因为它是到i位置最大
//    的差值,其他值不可能比i还要大.)

//    如果大于,则将两个对头靠前的那个丢掉,即出队,再比较对头,并且记录下
//    出队的位置下标,(因为此时出队的与到i的串的左边界有关),之后就是在
//    到i为止的最大值最小值之差如果大于等于low,这时i-上面记录的出队的较大
//    的位置就是到i的串的最大的长度。

//    感悟:

//    这道题想到了用两个单调队列分别保留最大值和最小值,但是出队的顺序,我并没有
//    很清楚,只知道一定会出队的,我之前的考虑是对两个对头比较,这是毫无疑问的,
//    之后对那个进行++操作呢,如果一起加,肯定是有问题,所以不是很清楚。之后看了看
//    各位大神的结题报告,发现,哪个在前面就出去就可以了,最后出队的取个最大的就是
//    左边界-1的值。
//    行百里者半九十,恰恰是最后的十让人撕心裂肺,欲罢不能,继续加油



#include 
#include 
#include 
#include 
using namespace std;
const int MAX_N = 1e5 + 1000;

int n,low,up;
int a[MAX_N];
int deqmi[MAX_N];
int deqmx[MAX_N];

void input(){
    for (int i = 1;i <= n; i++){
        cin >> a[i];
    }
}

void solve(){
    int head1 = 0,tail1 = 0;
    int head2 = 0,tail2 = 0;
    int mx = 0;
    int last1=0,last2=0;
    for (int i=1;i<=n;i++){

        while(head1 < tail1 && a[deqmi[tail1-1]] >= a[i])
            tail1--;
        deqmi[tail1++] = i;
        while(head2 < tail2 && a[deqmx[tail2-1]] <= a[i])
            tail2--;
        deqmx[tail2++] = i;

        while(a[deqmx[head2]] - a[deqmi[head1]]>up){
        //    while(head1 < tail1 && a[deqmx[head1]] - a[deqmi[head2] >= )
            if (deqmx[head2]>deqmi[head1]){
                last1 = deqmi[head1++];
            }else {
                last2 = deqmx[head2++];
            }
        }

        if (a[deqmx[head2]] - a[deqmi[head1]] >= low){
            mx = max(mx,i-max(last1,last2));
        }
    }

    cout << mx << endl;

}

int main(){
    ios::sync_with_stdio(false);
    while(cin >> n >> low >> up){
        input();
        solve();
    }
}

你可能感兴趣的:(Data,structure,hdu)