BZOJ P1342 [Baltic2007] 静音问题 【单调队列】

大概先解释一下题意:

给定序列中有多少个长度为 m 的区间中最大值与最小值的差 c ,输出左端点。如果无输出,则输出 N O N E

给定题意之后这道是不是就变得十分简单了?

由于 n 的范围有点大,用 S T L 也许会 T L E ,不过这道题的时间范围是 3 s ,应该可以过吧?

当然这道题除去 S T L 肯定还是有更加优秀的做法的,比如:单调队列

维护两个单调队列一个最大值一个最小值,然后就 O ( n ) 扫一遍。

参考代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int Max=1e6+5;
struct Node{
    int V,Id;
}P1[Max],P2[Max];
int N,M,C,A[Max],Mark,Head1=1,Head2=1,Tail1,Tail2;
int main(){
    int I,J,K;
    scanf("%d%d%d",&N,&M,&C);
    for(I=1;I<=N;I++){
        scanf("%d",&A[I]);
    }
    for(I=1;I<=N;I++){
        while(Head1<=Tail1&&I-P1[Head1].Id>=M){
            Head1++;
        }
        while(Head2<=Tail2&&I-P2[Head2].Id>=M){
            Head2++;
        }
        while(Head1<=Tail1&&A[I]>=P1[Tail1].V){
            Tail1--;
        }
        while(Head2<=Tail2&&A[I]<=P2[Tail2].V){
            Tail2--;
        }
        ++Tail1;P1[Tail1].Id=I;P1[Tail1].V=A[I];
        ++Tail2;P2[Tail2].Id=I;P2[Tail2].V=A[I];
        if(I>=M&&P1[Head1].V-P2[Head2].V<=C){
            printf("%d\n",I+1-M);Mark=1;
        }
    }
    if(Mark==0){
        puts("NONE");
    }
}

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/81167171