[HAOI2007]理想的正方形 单调队列 暴力

Code:

#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
#define maxn 1002
#define ll long long
#define inf 100000000000
int minv[maxn][maxn], maxv[maxn][maxn];
struct Node{
    ll val;
    int pos;
    Node(ll val=0,int pos=0):val(val),pos(pos){}
};
deque<Node>Q[2];
int main(){
    //freopen("input.in","r",stdin);
    int a,b,n;
    ll ans=inf,p;
    scanf("%d%d%d",&a,&b,&n);
    for(int i=1;i<=a;++i){
        for(int j=1;j<=b;++j) {
            scanf("%lld",&p);
            while(!Q[0].empty()&&Q[0].front().pos<j-n+1)Q[0].pop_front();
            while(!Q[1].empty()&&Q[1].front().pos<j-n+1)Q[1].pop_front();
            while(!Q[0].empty()&&Q[0].back().val>=p) Q[0].pop_back();
            while(!Q[1].empty()&&Q[1].back().val<=p) Q[1].pop_back();
            Q[0].push_back(Node(p,j)),Q[1].push_back(Node(p,j));
            if(j>=n) minv[i][j]=Q[0].front().val, maxv[i][j]=Q[1].front().val;
        }
        while(!Q[0].empty())Q[0].pop_back();
        while(!Q[1].empty())Q[1].pop_back();
    }
    for(int i=n;i<=b;++i){
        for(int j=1;j<=a;++j){
            while(!Q[0].empty()&&Q[0].front().pos<j-n+1)Q[0].pop_front();
            while(!Q[1].empty()&&Q[1].front().pos<j-n+1)Q[1].pop_front();
            while(!Q[0].empty()&&Q[0].back().val>=minv[j][i]) Q[0].pop_back();
            while(!Q[1].empty()&&Q[1].back().val<=maxv[j][i]) Q[1].pop_back();
            Q[0].push_back(Node(minv[j][i],j)),Q[1].push_back(Node(maxv[j][i],j));
            if(j>=n) ans=min(ans,Q[1].front().val-Q[0].front().val);
        }
        while(!Q[0].empty())Q[0].pop_back();
        while(!Q[1].empty())Q[1].pop_back();
    }
    printf("%lld",ans);
    return 0;
}

  

原文地址:https://www.cnblogs.com/guangheli/p/9919772.html

时间: 2024-10-09 16:43:16

[HAOI2007]理想的正方形 单调队列 暴力的相关文章

HAOI2007 理想的正方形 单调队列

单调队列 by   GeneralLiu 滑动窗口是比较裸的单调队列 理想的正方形   就拔高了一个层次(多了一维) 有一个a*b的整数组成的矩阵 现请你从中找出一个n*n的正方形区域 使得该区域所有数中的最大值和最小值的差最小 只写MAX了,MIN一个道理,懒 不写了 先横着跑单调队列 维护许多长度为 n 的 横着的MAX 存在数组 map1[][] 中 再对数组 map1[][] 竖着跑单调队列 就维护了 许多 n*n 的 矩阵的MAX MIN同理 在竖着跑单调队列时 顺便MAX 与 MIN

P2216 [HAOI2007]理想的正方形 - 单调队列

这种矩形问题常用单调队列优化枚举(通过贪心取最优降低了一个维度的枚举) 推荐这道题也要做一做:[ZJOI2007]棋盘制作 单调队列的空间记得开大点! 反正内存够用 注意,这题正方形边长是固定的! 暴力算法是枚举上边界所在的行,左边界所在的列,通过这两个个信息确定一个正方形,然后预处理出一行中从第i个点到i+n个点的最值,再扫一遍这个正方形的行,复杂度是N^3 预处理的时候,复杂度也是N^3...考虑用单调队列来维护,枚举到一行,看做一个序列,求长度为n的区间最值,就是一个滑动窗口,如果不大明白

[BZOJ1047] [HAOI2007] 理想的正方形 (单调队列)

Description 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. Input 第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数.每行相邻两数之间用一空格分隔.100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100 Output 仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值. Sample In

BZOJ 1047 HAOI2007 理想的正方形 单调队列

题目大意:给定一个a*b的矩阵,求一个n*n的子矩阵,使矩阵中的最大值与最小值之差最小 对于每行维护一个单调递减的队列.再弄一个竖着的队列.维护n个格子之内的最大值就可以 两遍统计出最大值和最小值 然后得到ans就可以 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 1010 using namespace std; struct abcd

洛谷OJ 2216 理想的正方形 单调队列(二维)

https://www.luogu.org/problem/show?pid=2216 题意:给出a*b矩形 从中找到一个n*n正方形,其(最大值-最小值之差)最小,a,b<=1e3,n<=100暴力枚举正方形右下角,如何快速算出其最大值和最小值?先用单调队列预处理出ma[i][j] 表示(i,j)以第i行j列结尾长度为n的最大值/在枚举列之后,对同一个列,由于已经知道该列 每行长度为n的最值 则在次利用单调队列,从上往下扫描行,求出(i,j)为右下角的矩形的最值即可 #include <

BZOJ 1047 HAOI 2007 理想的正方形 单调队列

题目大意:给出一个矩阵,求出一个k*k的子矩阵,使得这个矩阵中最大值和最小值的差最小,输出这个差值. 思路:利用单调队列维护每一行的数字,求出一个数字前面k个数字中的最大值和最小值,然后在列上暴力求出真个矩阵的最大值和最小值,总时间复杂度O(M*M+M*M*K). CODE: #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algor

BZOJ 1047 理想的正方形(单调队列)

刚开始用二维RMQ直接给超内存了... 用单调队列可以做到O(n^2)的复杂度.具体是先把每行用单调队列处理一下.再把处理后的用列单调队列处理下. # include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # in

【单调队列】bzoj1047 [HAOI2007]理想的正方形

先把整个矩阵处理成b[n][m-K+1].c[n][m-K+1]大小的两个矩阵,分别存储每行每K个数中的最大.最小值,然后再通过b.c处理出d.e分别表示K*K大小的子矩阵中的最大.最小值即可.单调队列暴力. #include<cstdio> #include<algorithm> using namespace std; #define N 1001 int n,m,K,a[N][N],b[N][N],c[N][N],q[N],head,tail,d[N][N],e[N][N];

[BZOJ1047][HAOI2007]理想的正方形

1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 3481  Solved: 1917 [Submit][Status][Discuss] Description 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值 的差最小. Input 第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数.每 行相邻