洛谷P2216 理想的正方形(单调队列)

洛谷P2216 理想的正方形

题目链接

思路:

直接暴力显然不可行,可以发现每一个矩形向右边扩展时是一列一列增加,于是可以想到单调队列,用数组来维护当前每列的最大值。因为行也有限制,所以还要用一个单调队列来维护行的信息。
做法大概就是每次扩展一行,然后求出每一列当前的最大值,之后再一列一列来搞。

详见代码吧:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1005, M = 105;
int a, b, n;
int mp[N][N], tmp[N][2];
int q1[N][N], l1[N], r1[N], q2[N][N], l2[N], r2[N];
int Q1[N], Q2[N];
int main() {
    ios::sync_with_stdio(false); cin.tie(0) ;
    cin >> a >> b >> n;
    for(int i = 1; i <= a; i++) for(int j = 1; j <= b; j++) cin >> mp[i][j] ;
    for(int i = 1; i <= b; i++) l1[i] = l2[i] = 1;
    int ans = 2e9;
    for(int i = 1; i <= a; i++) {
        for(int j = 1; j <= b; j++) {
            while(l1[j] <= r1[j] && mp[q1[j][r1[j]]][j] <= mp[i][j]) r1[j]--;
            q1[j][++r1[j]] = i ;
            while(l2[j] <= r2[j] && mp[q2[j][r2[j]]][j] >= mp[i][j]) r2[j]--;
            q2[j][++r2[j]] = i ;
            while(l1[j] <= r1[j] && i + 1 - q1[j][l1[j]] > n) l1[j]++;
            while(l2[j] <= r2[j] && i + 1 - q2[j][l2[j]] > n) l2[j]++;
        }
        for(int j = 1; j <= b; j++) tmp[j][0] = mp[q1[j][l1[j]]][j], tmp[j][1] = mp[q2[j][l2[j]]][j];
        int mx = 0, mn = 1e9 + 1;
        int cc1, cc2;
        int L1 = 1, R1 = 0, L2 = 1, R2 = 0;
        for(int j = 1; j <= b; j++) {
            while(L1 <= R1 && tmp[Q1[R1]][0] <= tmp[j][0]) R1--;
            while(L2 <= R2 && tmp[Q2[R2]][1] >= tmp[j][1]) R2--;
            Q1[++R1] = j ;
            Q2[++R2] = j ;
            while(L1 <= R1 && j + 1 - Q1[L1] > n) L1++;
            while(L2 <= R2 && j + 1 - Q2[L2] > n) L2++;
            if(i >= n && j >= n) ans = min(ans, tmp[Q1[L1]][0] - tmp[Q2[L2]][1]);
//            cout << i << ' ' << Q1[L1] << ' ' << Q2[L2] << '
';
        }
//        cout << "---------------" << '
' ;
    }
    cout << ans;
    return 0;
}
/*
5 4 2
1 2 3 4
5 6 7 8
9 8 7 6
1 3 2 3
1 2 3 4
*/
原文地址:https://www.cnblogs.com/heyuhhh/p/10891252.html