E11【模板】单调队列 滑动窗口最值

E11【模板】单调队列 滑动窗口最值_哔哩哔哩_bilibili

 

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

// 单调队列 O(n)
#include<iostream>
using namespace std;

const int N=1000010;
int n,k,a[N],q[N];

int main(){
  scanf("%d%d",&n,&k);
  for(int i=1; i<=n; i++) scanf("%d",&a[i]);
  
  for(int i=1,h=1,t=0; i<=n; i++){
    while(h<=t && q[h]<i-k+1) h++;    //队头出队(队列不空且队头元素滑出窗口) 
    while(h<=t && a[q[t]]>=a[i]) t--; //队尾出队(队列不空且新元素更优)
    q[++t]=i;                         //队尾入队(存储下标 方便判断队头出队)
    if(i>=k) printf("%d ",a[q[h]]);   //输出最小值
  }
  puts("");
  
  for(int i=1,h=1,t=0; i<=n; i++){
    while(h<=t && q[h]<i-k+1) h++;
    while(h<=t && a[q[t]]<=a[i]) t--;
    q[++t]=i;
    if(i>=k) printf("%d ",a[q[h]]);
  }
}

 

P1440 求m区间内的最小值 - 洛谷

P2032 扫描 - 洛谷

P2216 [HAOI2007] 理想的正方形 - 洛谷

1. 分步做,把矩形区的最值先按行压缩到到一格存储,后按列压缩到一格存储

2. 枚举行,横向滑动窗口,把每行的窗口最值存储在 maxv[i][j], minv[i][j]

3. 枚举列,竖向滑动窗口,把每列的窗口最值存储在 c[i], d[i]

#include<iostream>
using namespace std;

const int N=1010;
int n,m,k;
int w[N][N],minv[N][N],maxv[N][N]; //maxv[i][j]:第i行,j-k+1~j列的最大值
int q[N],a[N],b[N],c[N],d[N];      //a[i]:第i行,j-k+1~j列的最大值
                                   //c[i]:第i-k+1~i行,j-k+1~j列的最大值

void get_max(int a[],int b[],int m){
  for(int i=1,h=1,t=0; i<=m; i++){
    while(h<=t && q[h]<i-k+1) h++;
    while(h<=t && a[q[t]]<=a[i]) t--;
    q[++t]=i;
    b[i]=a[q[h]];
  }
}
void get_min(int a[],int b[],int m){
  for(int i=1,h=1,t=0; i<=m; i++){
    while(h<=t && q[h]<i-k+1) h++;
    while(h<=t && a[q[t]]>=a[i]) t--;
    q[++t]=i;
    b[i]=a[q[h]];
  }
}
int main(){
  scanf("%d%d%d",&n,&m,&k);
  for(int i=1; i<=n; i++)
    for(int j=1; j<=m; j++) scanf("%d",&w[i][j]);
    
  for(int i=1; i<=n; i++){ //枚举行
    get_max(w[i],maxv[i],m); //横滑窗口  
    get_min(w[i],minv[i],m);
  }
  
  int res=1e9;
  for(int j=k; j<=m; j++){ //枚举列
    for(int i=1; i<=n; i++) a[i]=maxv[i][j],b[i]=minv[i][j];
    get_max(a,c,n); //竖滑窗口
    get_min(b,d,n);
    for(int i=k;i<=n;i++) res=min(res,c[i]-d[i]);
  }
  printf("%d\n",res);
}

 

posted @ 2023-04-10 09:24  董晓  阅读(1729)  评论(0)    收藏  举报