玄关 单调队列0分求助 P2216
查看原帖
玄关 单调队列0分求助 P2216
932267
xd22fuzhu楼主2023/12/23 19:16

求大佬帮助,玄关,代码码风良好,有注释谢谢!

传送门:https://www.luogu.com.cn/problem/P2216

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1005;
long long s[MAXN][MAXN],q[MAXN];
long long mafirst[MAXN][MAXN],ma[MAXN][MAXN];
long long mifirst[MAXN][MAXN],mi[MAXN][MAXN];
int main () {
	long long a,b,n;
	cin >> a >> b >> n;
	for (int i = 1; i <= a; i++)
	    for (int j = 1; j <= b; j++)
			cin >> s[i][j];//读入数据
	
	//最大值计算
	for (int i = 1; i <= a; i++) {
		int head = 0, tail = 0;
		for (int j = 1; j <= b; j++) {
			while (head < tail && q[head] + n <= j)
				head++;
			while (head < tail && s[i][q[tail - 1]] < s[i][j])
				tail--;
			q[tail] = j;
			tail++;
			if (j >= n) mafirst[i][j - n + 1] = s[i][q[head]];
		}
	}//先算列
	for (int i = 1; i <= b - n + 1; i++) {
		int head = 0, tail = 0;
		for (int j = 1; j <= a - n + 1; j++) {
			while (head < tail && q[head] + n <= j)
				head++;
			while (head < tail && s[q[tail - 1]][i] < s[j][i])
				tail--;
			q[tail] = j;
			tail++;
			if (j >= n) ma[j - n + 1][i] = s[q[head]][i];
		}
	}//再算行	
	
	//计算最小值
	for (int i = 1; i <= a - n + 1; i++) {
		int head = 0, tail = 0;
		for (int j = 1; j <= b - n + 1; j++) {
			while (head < tail && q[head] + n <= j)
				head++;
			while (head < tail && s[i][q[tail - 1]] > s[i][j])
				tail--;
			q[tail] = j;
			tail++;
			if (j >= n) mifirst[i][j - n + 1] = s[i][q[head]];
		}
	}//先算列
	for (int i = 1; i <= b; i++) {
		int head = 0, tail = 0;
		for (int j = 1; j <= a; j++) {
			while (head < tail && q[head] + n <= j)
				head++;
			while (head < tail && s[q[tail - 1]][i] > s[j][i])
				tail--;
			q[tail] = j;
			tail++;
			if (j >= n) mi[j - n + 1][i] = s[q[head]][i];
		}
	}//再算行
	
	long long ans = 1145141919810;
	for (int i = 1; i <= a - n + 1; i++)
		for (int j = 1; j <= b - n + 1; j++)
			ans = min(ans,ma[i][j] - mi[i][j]);
	cout << ans << endl;
	return 0;
}
2023/12/23 19:16
加载中...