题目地址: bzoj1047
我好菜啊qwq,这道题调了一万年
n = 1000 理论上可以用数据结构水过去,,,但是我太菜了不会qwq
做法差不多就是先维护在某一行的连续n个数的最值,用g[i][j]表示,在这个基础上维护以某个点为右下角的n * n 的矩形内的最值,用f[i][j]表示。
就……完了
min 和 max 分别维护一下就好了
然而这破题还是调了快1个小时qwq
//gdb真好用辣鸡dev老是炸
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
using namespace std;
const int MAXN = 1000 + 10;
int a, b, n;
int map[MAXN][MAXN];
int q1[MAXN], q2[MAXN], l(1), r(0);
int fmx[MAXN][MAXN], fmn[MAXN][MAXN];
int gmx[MAXN][MAXN], gmn[MAXN][MAXN];
void solve_mx() {
for (int i=1; i<=a; ++i) {
l = 1, r = 0;
for (int j=1; j<=b; ++j) {
while (l <= r && q1[r] <= map[i][j]) -- r;
++ r;
q1[r] = map[i][j], q2[r] = j;
while (l <= r && j - q2[l] + 1 > n) ++ l;
gmx[i][j] = q1[l];
}
}
for (int j=1; j<=b; ++j) {
l = 1, r = 0;
for (int i=1; i<=a; ++i) {
while (l <= r && q1[r] <= gmx[i][j]) -- r;
++ r;
q1[r] = gmx[i][j], q2[r] = i;
while (l <= r && i - q2[l] + 1 > n) ++ l;
fmx[i][j] = q1[l];
}
}
}
void solve_mn() {
for (int i=1; i<=a; ++i) {
l = 1, r = 0;
for (int j=1; j<=b; ++j) {
while (l <= r && q1[r] >= map[i][j]) -- r;
++ r;
q1[r] = map[i][j], q2[r] = j;
while (l <= r && j - q2[l] + 1 > n) ++ l;
gmn[i][j] = q1[l];
}
}
for (int j=1; j<=b; ++j) {
l = 1, r = 0;
for (int i=1; i<=a; ++i) {
while (l <= r && q1[r] >= gmn[i][j]) -- r;
++ r;
q1[r] = gmn[i][j], q2[r] = i;
while (l <= r && i - q2[l] + 1 > n) ++ l;
fmn[i][j] = q1[l];
}
}
}
int main() {
ios::sync_with_stdio(0);
cin >> a >> b >> n;
for (int i=1; i<=a; ++i) {
for (int j=1; j<=b; ++j) {
cin >> map[i][j];
}
}
solve_mx();
solve_mn();
int ans = INT_MAX;
for (int i=n; i<=a; ++i) {
for (int j=n; j<=b; ++j) {
ans = min(ans, fmx[i][j] - fmn[i][j]);
}
}
cout << ans;
}
我好菜啊qwq