1091. 理想的正方形

题目链接

1091. 理想的正方形

有一个 a×b 的整数组成的矩阵,现请你从中找出一个 n×n 的正方形区域,使得该区域所有数中的最大值和最小值的差最小。

输入格式

第一行为三个整数,分别表示 a,b,n 的值;

第二行至第 a+1 行每行为 b 个非负整数,表示矩阵中相应位置上的数。

输出格式

输出仅一个整数,为 a×b 矩阵中所有“n×n 正方形区域中的最大整数和最小整数的差值”的最小值。

数据范围

2a,b1000,
na,nb,n100,
矩阵中的所有数都不超过 109

输入样例:

5 4 2 1 2 5 6 0 17 16 0 16 17 2 1 2 10 2 1 1 2 2 2

输出样例:

1

解题思路

二维滑动窗口

要求 n×n 的滑动窗口的极值,不妨先将每一行的长度为 n 的极值求出,即一维滑动窗口问题,这样的极值共有 n 个,且在滑动窗口每行的最后一列,即每行的极值都在同一列中体现,再对这样的列求一遍一维滑动窗口即可

  • 时间复杂度:O(ab)

代码

// Problem: 理想的正方形 // Contest: AcWing // URL: https://www.acwing.com/problem/content/description/1093/ // Memory Limit: 64 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=1005; int n,m,k,a[N][N]; int row_min[N][N],row_max[N][N],mx[N],mn[N],tmp[N]; int q[N],hh,tt; void get_min(int a[],int b[],int n) { hh=tt=0; for(int i=1;i<=n;i++) { while(hh<=tt&&i-q[hh]+1>k)hh++; while(hh<=tt&&a[q[tt]]>=a[i])tt--; q[++tt]=i; b[i]=a[q[hh]]; } } void get_max(int a[],int b[],int n) { hh=tt=0; for(int i=1;i<=n;i++) { while(hh<=tt&&i-q[hh]+1>k)hh++; while(hh<=tt&&a[q[tt]]<=a[i])tt--; q[++tt]=i; b[i]=a[q[hh]]; } } 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",&a[i][j]); for(int i=1;i<=n;i++)get_min(a[i],row_min[i],m),get_max(a[i],row_max[i],m); int res=1e9; for(int j=k;j<=m;j++) { for(int i=1;i<=n;i++)tmp[i]=row_min[i][j]; get_min(tmp,mn,n); for(int i=1;i<=n;i++)tmp[i]=row_max[i][j]; get_max(tmp,mx,n); for(int i=k;i<=n;i++)res=min(res,mx[i]-mn[i]); } printf("%d",res); return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16962566.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示