社区讨论

萌新,妹子,刚学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 条回复,欢迎继续交流。

正在加载回复...