• 2019牛客多校第三场F Planting Trees(单调队列)题解


    题意:

    求最大矩阵面积,要求矩阵内数字满足(max - min < m)

    思路:

    枚举上下长度,在枚举的时候可以求出每一列的最大最小值(cmax,cmin),这样问题就变成了求一行数,要你得到(max - min < m)的最长长度。用单调队列(O(n))求解。总复杂度(O(n^3))

    代码:

    #include<map>
    #include<set>
    #include<cmath>
    #include<cstdio>
    #include<stack>
    #include<ctime>
    #include<vector>
    #include<queue>
    #include<cstring>
    #include<string>
    #include<sstream>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int maxn = 500 + 5;
    const int INF = 0x3f3f3f3f;
    const ll MOD = 1e9 + 7;
    using namespace std;
    int n, m;
    int a[maxn][maxn];
    int cmax[maxn], cmin[maxn];  //递减 递增
    int maxq[maxn], minq[maxn];
    int getans(){
        int maxhead = 0, maxtail = 0, minhead = 0, mintail = 0;
        int l = 1;
        int len = 0;
        for(int i = 1; i <= n; i++){
            while(maxhead < maxtail && cmax[i] > cmax[maxq[maxtail - 1]]) maxtail--;
            maxq[maxtail++] = i;
            while(minhead < mintail && cmin[i] < cmin[minq[mintail - 1]]) mintail--;
            minq[mintail++] = i;
    
            while(minhead < mintail && maxhead < maxtail && cmax[maxq[maxhead]] - cmin[minq[minhead]] > m){
                l = min(maxq[maxhead], minq[minhead]) + 1;  //跳到l + 1
                while(minhead < mintail && minq[minhead] < l) minhead++;
                while(maxhead < maxtail && maxq[maxhead] < l) maxhead++;
            }
    
            len = max(len, i - l + 1);
        }
        return len;
    }
    int main(){
        int T;
        scanf("%d", &T);
        while(T--){
            scanf("%d%d", &n, &m);
            for(int i = 1; i <= n; i++){
                for(int j = 1; j <= n; j++){
                    scanf("%d", &a[i][j]);
                }
            }
            int ans = 0;
            for(int i = 1; i <= n; i++){    //从i
                for(int j = 1; j <= n; j++){
                    cmax[j] = -1;
                    cmin[j] = INF;
                }
                for(int j = i; j <= n; j++){    //到j
                    for(int k = 1; k <= n; k++){
                        cmax[k] = max(cmax[k], a[j][k]);
                        cmin[k] = min(cmin[k], a[j][k]);
                    }
                    ans = max(ans, (j - i + 1) * getans());
    
                }
            }
            printf("%d
    ", ans);
        }
    
        return 0;
    }
    
    
    
  • 相关阅读:
    P4014 分配问题 网络流
    P4015 运输问题 网络流问题
    P4013 数字梯形问题 网络流
    网络流 P2770 航空路线问题
    网络流之最小费用最大流 P1251 餐巾计划问题
    二分图定理
    数论 C
    网络流 E
    网络流 之 P2766 最长不下降子序列问题
    scp使用
  • 原文地址:https://www.cnblogs.com/KirinSB/p/11248669.html
Copyright © 2020-2023  润新知