P2216 理想的正方形 單調隊列 (二維)

題目鏈接:https://www.luogu.org/problem/P2216

題意:求給定n*m的矩形中所有k*k的正方形塊中最大值最小值之差(極差)最小

哇,大神的思路真的很帥

單調隊列對每一行求一個k項最大最小

用X[i][j]表示第i行小於j-k+1~j的最大值

用X[i][j]表示第i行小於j-k+1~j的最大值

然後處理完行之後,用X,x數組作爲基礎對每一列求最大最小,用Y,y表示

這樣處理完的Y[i][j]就表示以i,j爲右下角的k*k矩形的最大值

這樣處理完的y[i][j]就表示以i,j爲右下角的k*k矩形的最小值

給他起個名字就叫二位單調隊列吧QAQ~

此圖是偷的~

代碼如下啦:


//#pragma comment (linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
#include<stdio.h>
#include<string.h>
#include<string>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<set>
#include<stack>
#include<vector>
#include<map>
#include<queue>
#include<list>
#include<time.h>
#include<bitset>

#define myself i,l,r
#define lson i<<1
#define rson i<<1|1
#define Lson i<<1,l,mid
#define Rson i<<1|1,mid+1,r
#define half (l+r)/2
#define lowbit(x) x&(-x)
#define min4(a, b, c, d) min(min(a,b),min(c,d))
#define min3(x, y, z) min(min(x,y),z)
#define max3(x, y, z) max(max(x,y),z)
#define max4(a, b, c, d) max(max(a,b),max(c,d))
#define pii make_pair
#define pr pair<int,int>
typedef unsigned long long ull;
typedef long long ll;
const int inff = 0x3f3f3f3f;
const long long inFF = 9223372036854775807;
const int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
const int mdir[8][2] = {0, 1, 0, -1, 1, 0, -1, 0, 1, 1, -1, 1, 1, -1, -1, -1};
const double eps = 1e-10;
const double PI = acos(-1.0);
const double E = 2.718281828459;
using namespace std;
const int mod=1e9+7;
const int maxn=1005;
int a[maxn][maxn];
int X[maxn][maxn],x[maxn][maxn],Y[maxn][maxn],y[maxn][maxn];
int Q[maxn],q[maxn];
int main()
{
    int n,m,k;
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&a[i][j]);
    for(int i=1;i<=n;i++)
    {
        int l=0,r=0,L=0,R=0;
        Q[0]=0,q[0]=0;
        for(int j=1;j<=m;j++)
        {
            while(l<=r&&a[i][j-1]<=a[i][q[r]]) r--;
            while(L<=R&&a[i][j-1]>=a[i][Q[R]]) R--;
            q[++r]=j-1,Q[++R]=j-1;
            while(l<=r&&q[l]<=j-k) l++;
            while(L<=R&&Q[L]<=j-k) L++;
            x[i][j]=min(a[i][q[l]],a[i][j]);
            X[i][j]=max(a[i][Q[L]],a[i][j]);
        }
    }
    for(int i=k;i<=m;i++)
    {
        int l=0,r=0,L=0,R=0;
        Q[0]=0,q[0]=0;
        for(int j=1;j<=n;j++)
        {
            while(l<=r&&x[j-1][i]<=x[q[r]][i]) r--;
            while(L<=R&&X[j-1][i]>=X[Q[R]][i]) R--;
            q[++r]=j-1,Q[++R]=j-1;
            while(l<=r&&q[l]<=j-k) l++;
            while(L<=R&&Q[L]<=j-k) L++;
            y[j][i]=min(x[j][i],x[q[l]][i]);
            Y[j][i]=max(X[j][i],X[Q[L]][i]);
        }
    }
    int ans=inff;
    for(int i=k;i<=n;i++)
        for(int j=k;j<=m;j++)
            ans=min(ans,Y[i][j]-y[i][j]);
    cout<<ans<<endl;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章