题目
双指针:
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 85, M = 1e5+10;
int g[N][M];
int n, m, lim;
int ans = 1;
int main()
{ios::sync_with_stdio(0);cin.tie(0);cin >> n >> m;for(int i = 1; i <= n; i++)for(int j = 1; j <= m; j++)cin >> g[i][j];cin >> lim;for(int a = 1; a <= n; a++){for(int b = a; b <= n; b++){int maxx = 0;int minn = 1e5+10;int minpos = 1;int maxpos = 1;for(int l = 1, r = 1; r <= m; r++){for(int k = a; k <= b; k++){maxx = max(maxx, g[k][r]);minn = min(minn, g[k][r]);if(maxx == g[k][r]) maxpos = r;if(minn == g[k][r]) minpos = r;}if(maxx - minn <= lim) ans = max(ans, (b - a + 1) * (r - l + 1));else{l = min(maxpos, minpos) + 1;maxx = 0;minn = 1e5+10;if(l <= r){for(int i = a; i <= b; i++){for(int j = l; j <= r; j++){maxx = max(maxx, g[i][j]);minn = min(minn, g[i][j]);if(maxx == g[i][j]) maxpos = j;if(minn == g[i][j]) minpos = j;}}}}}}}cout << ans;
}
另一个形式
#include <bits/stdc++.h>
using namespace std;
const int N = 85, M = 1e5+10;
int g[N][M];
int n, m, lim;
int ans = 1;int main()
{ios::sync_with_stdio(0);cin.tie(0);cin >> n >> m;for(int i = 1; i <= n; i++)for(int j = 1; j <= m; j++)cin >> g[i][j];cin >> lim;// 遍历所有可能的起点行和终点行for(int a = 1; a <= n; a++){for(int b = a; b <= n; b++){// 使用滑动窗口法对每一列进行计算int l = 1;int maxx = g[a][1];int minn = g[a][1];int posmax = 1;int posmin = 1;for(int r = 1; r <= m; r++){// 更新当前窗口的最大值和最小值for(int k = a; k <= b; k++){maxx = max(maxx, g[k][r]);minn = min(minn, g[k][r]);if(maxx == g[k][r]) posmax = r;if(minn == g[k][r]) posmin = r;}while (maxx - minn > lim && l <= r){l = min(posmax, posmin) + 1;// 重新计算当前窗口的最大值和最小值maxx = g[a][l];minn = g[a][l];for(int k = a; k <= b; k++){for(int j = l; j <= r; j++){maxx = max(maxx, g[k][j]);minn = min(minn, g[k][j]);if(maxx == g[k][j]) posmax = j;if(minn == g[k][j]) posmin = j;}}}// 更新最大面积ans = max(ans, (b - a + 1) * (r - l + 1));}}}cout << ans;
}
二分 + 单调队列:
#include <bits/stdc++.h>
using namespace std;
const int N = 85, M = 1e5+10;
int g[N][M], qmax[M], qmin[M], hmax, hmin, tmax, tmin;
int colmax[M], colmin[M];
int ans = 1;
int n, m, lim;
bool check(int x)
{hmax = hmin = 0, tmax = tmin = -1;for(int i = 1; i <= m; i++){while(hmax <= tmax && colmax[qmax[tmax]] <= colmax[i]) tmax--;while(hmin <= tmin && colmin[qmin[tmin]] >= colmin[i]) tmin--;qmax[++tmax] = i;qmin[++tmin] = i;if(qmax[hmax] < i - x + 1) hmax++;if(qmin[hmin] < i - x + 1) hmin++;if(i >= x && colmax[qmax[hmax]] - colmin[qmin[hmin]] <= lim) return true;}return false;
}
int get()
{int l = 1, r = m;while(l < r){int mid = (l + r + 1) >> 1;if(check(mid)) l = mid;else r = mid-1;}if(check(l)) return l;return 0;
}
int main()
{ios::sync_with_stdio(0);cin.tie(0);cin >> n >> m;for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++)cin >> g[i][j];}cin >> lim;for(int i = 1; i <= n; i++){for(int t = 1; t <= m; t++){colmax[t] = 0;colmin[t] = 1e6;}for(int j = i; j <= n; j++){for(int t = 1; t <= m; t++){colmax[t] = max(colmax[t], g[j][t]);colmin[t] = min(colmin[t], g[j][t]);}int maxlen = get();ans = max(ans, maxlen * (j - i + 1));}}cout << ans;
}