【简●解】[HAOI2007] 理想的正方形

【简●解】[HAOI2007] 理想的正方形

可恶的\(DP\)


【题目大意】

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

【分析】

在暴力中想到优化,模仿曾经求二维前缀和的做法,先在每行求区间长度为\(n\)的最大值和最小值,再在此基础上求列上的最大值和最小值,则求得的即为单个\(n*n\)正方形矩阵中的最大值和最小值。(仔细体味下)

用单调队列就可以搞定,和滑动窗口类似。

【Code】

一个挣扎在英语一线的苦逼\(Oier\)。。。敲代码背单词。。。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int N = 1000 + 5;
const int INF = 0x7fffffff;
inline int read(){
    int f = 1, x = 0;char ch;
    do { ch = getchar(); if (ch == '-') f = -1; } while (ch < '0'||ch>'9');
    do {x = x*10+ch-'0'; ch = getchar(); } while (ch >= '0' && ch <= '9'); 
    return f*x;
}
int a, b, n, aa, bb, maps[N][N], ans = INF;
int shallow[N][N];// 肤浅的 adj. ---X最大值 
int reform[N][N];// 改革,改进 v. ---X最小值 
int allergic[N][N];// 敏感的 adj. ---Y最大值
int association[N][N];//协会,交往 n. ---Y最小值 
int violence[20 * N];// 暴力行为 adj. ---队列 
int head = 1, tail = 0;

int main(){
    a = read(), b = read(), n = read();
    for (int i = 1;i <= a; ++i) {
        for (int j = 1;j <= b; ++j) {
            maps[i][j] = read();
        }
    }
    aa = a - n + 1;
    bb = b - n + 1;
    
    for (int i = 1;i <= a; ++i) {
        head = 1, tail = 0;
//      printf("rand %d : %d - %d \n", i, head, tail) ;     
        for (int j = 1;j <= b; ++j) {
            while (maps[i][violence[tail]] <= maps[i][j] && head <= tail) tail--;
            violence[++tail] = j;           
            while (head <= tail && violence[head] < j - n + 1) {
                head++;
            }
            shallow[i][j] = maps[i][violence[head]];
        }
    }
    
    for (int i = 1;i <= a; ++i) {
        head = 1, tail = 0;
//      printf("rand %d : %d - %d \n", i, head, tail) ;     
        for (int j = 1;j <= b; ++j) {
            while (maps[i][violence[tail]] >= maps[i][j] && head <= tail) tail--;
            violence[++tail] = j;           
            while (head <= tail && violence[head] < j - n + 1) {
                head++;
            }
            reform[i][j] = maps[i][violence[head]];
        }
    }

//  puts("");
//  for (int i = 1;i <= a; ++i) {
//      for (int j = 1; j <= b; ++j) {
//          printf("%d ", reform[i][j]);
//      }
//      puts("");
//  }   
    
    for (int j = 1;j <= b; ++j) {
        head = 1, tail = 0;
        for (int i = 1;i <= a; ++i) {
            while (shallow[violence[tail]][j] <= shallow[i][j] && head <= tail) tail--;
            violence[++tail] = i;           
            while (head <= tail && violence[head] < i - n + 1) {
                head++;
            }
            allergic[i][j] = shallow[violence[head]][j];
        }
    }

//  puts("");
//  for (int i = 1;i <= a; ++i) {
//      for (int j = 1; j <= b; ++j) {
//          printf("%d ", allergic[i][j]);
//      }
//      puts("");
//  }   
    
    for (int j = 1;j <= b; ++j) {
        head = 1, tail = 0;
        for (int i = 1;i <= a; ++i) {
            while (reform[violence[tail]][j] >= reform[i][j] && head <= tail) tail--;
            violence[++tail] = i;           
            while (head <= tail && violence[head] < i - n + 1) {
                head++;
            }
            association[i][j] = reform[violence[head]][j];          
        }
    }

//  puts("");
//  for (int i = 1;i <= a; ++i) {
//      for (int j = 1; j <= b; ++j) {
//          printf("%d ", association[i][j]);
//      }
//      puts("");
//  }   
    
    for (int i = n; i <= a; ++i) {
        for (int j = n; j <= b; ++j) {
            ans = min(ans, allergic[i][j] - association[i][j]);
        }
    }
    
    printf("%d", ans);
    return 0;
}

转载于:https://www.cnblogs.com/silentEAG/p/10901847.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值