社区讨论
萌新,妹子,刚学OI求助
P2216[HAOI2007] 理想的正方形参与者 7已保存回复 6
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 6 条
- 当前快照
- 1 份
- 快照标识符
- @mi6yn21b
- 此快照首次捕获于
- 2025/11/20 12:57 4 个月前
- 此快照最后确认于
- 2025/11/20 12:57 4 个月前
太弱了只会打个暴力的线段树,咋就WA了呢嘤嘤嘤。就A了第一个点,输出线段树的值后发现最大最小值也没啥问题啊……
CPP#include<bits/stdc++.h>
#define maxn 1008
#define inf 0x7f7f7f7f
using namespace std;
int n, m, k, ans = inf, a[maxn][maxn]; //nmk :abn
int mn[maxn][maxn<<2], mx[maxn][maxn<<2]; //mn[i], mx[i] 第i行的最小/最大值线段树
int lastmn[maxn][maxn], lastmx[maxn][maxn]; //第i行第j列开始向右的最值(记忆化)
void build(int line, int p, int l, int r){
if(l == r){
mn[line][p] = mx[line][p] = a[line][l];
return;
}
int mid = (l + r)>>1;
build(line, p<<1, l, mid);
build(line, p<<1|1, mid+1, r);
mn[line][p] = min(mn[line][p<<1], mn[line][p<<1|1]);
mx[line][p] = max(mx[line][p<<1], mn[line][p<<1|1]);
}
int querymn(int line, int p, int pl, int pr, int l, int r){
if(pr < l || pl > r) return inf;
if(l <= pl && pr <=r) return mn[line][p];
int mid = (pl + pr)>>1;
return min(querymn(line, p<<1, pl, mid, l, r), querymn(line, p<<1|1, mid+1, pr, l, r));
}
int querymx(int line, int p, int pl, int pr, int l, int r){
if(pr < l || pl > r) return -inf;
if(l <= pl && pr <=r) return mx[line][p];
int mid = (pl + pr)>>1;
return max(querymx(line, p<<1, pl, mid, l, r), querymx(line, p<<1|1, mid+1, pr, l, r));
}
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]);
build(i, 1, 1, m);
}
int MIN, MAX;
for(int i=1 ; i+k-1<=n ; i++){
for(int j=1 ; j+k-1<=m ; j++){ //左上角
MIN = inf;
MAX = -inf;
for(int line=i ; line<=i+k-1 ; line++){ //找每一行的最值
if(!lastmx[line][j]){ //是新遇到的一行(用mx判断,免得mn是0)
lastmn[line][j] = querymn(line, 1, 1, m, j, j+k-1);
lastmx[line][j] = querymx(line, 1, 1, m, j, j+k-1);
}
MIN = min(MIN, lastmn[line][j]);
MAX = max(MAX, lastmx[line][j]);
}
ans = min(ans, MAX - MIN);
}
}
printf("%d\n", ans);
return 0;
}
回复
共 6 条回复,欢迎继续交流。
正在加载回复...