Rt求助dalao

P1886 滑动窗口 /【模板】单调队列

Jia_k666 @ 2020-01-06 17:59:45

while(dq[l]+k<=i and l<=r) l++;

while(a[i]<a[dq[r]] and l<=r) r--;

单调队列中这句话是什么意思¿¿¿¿¿¿

求助dalao


by Arron_HC @ 2020-01-06 18:40:31

@Jia_k666

先说第一行(比较好理解)

若改成

while(dq[l]<=i-k and l<=r) l++;

就会好理解一些

意思是:若窗口中的元素个数多于k个,便将队首元素弹出,懂?


by Jia_k666 @ 2020-01-06 18:41:21

@Arron_HC e...懂


by Arron_HC @ 2020-01-06 18:42:57

@Jia_k666

第二行其实也不难,

while(a[i]<a[dq[r]] and l<=r) r--;

你可以参照第一篇题解模拟一下,如果队尾元素后紧跟着一个大于它的元素,那么,它在有生之年必然当不成最大值,故跳出。


by Jia_k666 @ 2020-01-06 18:44:27

@Arron_HC 如此明白的解析。。。。小人如此一拜


by Arron_HC @ 2020-01-06 18:44:38

@江挽


by RAYMOND_7 @ 2020-01-06 20:18:40

别写单调队列,线段树好得很

#include <cstdio>
#define ll long long
int a[1000004],tree[5000005],big[4000004];int n,m;
inline int min(int i,int j){
    return i<j?i:j;
}
inline int max(int i,int j){
    if(i>j) return i;
        return j;
}
inline void build(int k,int l,int r){
    if(l==r){tree[k]=a[l];return ;}
    build(k<<1,l,l+r>>1);
    build(k<<1|1,(l+r>>1)+1,r);
    tree[k]=min(tree[k<<1],tree[k<<1|1]);
}
void buil(int k,int l,int r){
    if(l==r){big[k]=a[l];return ;}
    buil(k<<1,l,l+r>>1);
    buil(k<<1|1,(l+r>>1)+1,r);
    big[k]=max(big[k<<1],big[k<<1|1]);
}
inline int minn(int k,int l,int r,int x,int y){
    if(l>y||r<x) return 2147483647;
    if(x<=l&&r<=y){return tree[k];}
    int mid=l+r>>1;
    return min(minn(k<<1,l,mid,x,y),minn(k<<1|1,mid+1,r,x,y));
}
inline int maxn(int k,int l,int r,int x,int y){
    if(l>y||r<x) return -2147483647;
    if(x<=l&&r<=y){return big[k];}
    int mid=l+r>>1;
    return max(maxn(k<<1,l,mid,x,y),maxn(k<<1|1,mid+1,r,x,y));
}
void read(int &x){
    x=0;int k=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') k=-1;ch=getchar();}
    while(ch<='9'&&ch>='0') {x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    x*=k;
    return ;
}
int l,r;
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){read(a[i]);}
    build(1,1,n);
    buil(1,1,n);
    for(int i=1;i<=n-m+1;++i){
        l=i;r=i+m-1;
        printf("%d ",minn(1,1,n,l,r));
    }
    printf("\n");
    for(int i=1;i<=n-m+1;++i){
        l=i;r=i+m-1;
        printf("%d ",maxn(1,1,n,l,r));
    }
    return 0;
}

|