zoukankan      html  css  js  c++  java
  • 2019 牛客暑期多校 第三场 F Planting Trees (单调队列+尺取)

    题目https://ac.nowcoder.com/acm/contest/883/F

    题意:求一个矩阵最大面积,这个矩阵的要求是矩阵内最小值与最大值差值<=m

    思路:首先我们仔细观察范围,我们就知道可以n^3,前面这题我(看付队博客)讲过求一个最大的什么矩阵就是分两种情况,

    第一种:枚举上下边界,转化为一维,复杂度n^3

    第二种:枚举下边界,转化为高楼问题,复杂度n^2

    这里显然复杂度可以n^3,我们就想一下三场循环,这题实际上就是找到矩阵内的最大值最小值

    第一层肯定是枚举上边界

    第二层我们要边枚举下边界边求当前列的最大最小值

    第三层 这里其实也就是转化为了一个一维的题,求一个序列内,每个有一个最大最小值,任意两点差值不超过m,然后问最大连续长度是多少

    这个其实很简单,我们用两个单调队列分别记录最大最小值,然后尺取过去即可,这里必须手动模拟队列,不然会超时。(亲测)

    附:我们第一层枚举上边界,第二层枚举下边界是有特殊原因的,这样方便O(n)求出所有最大值

    #include<bits/stdc++.h>
    #define maxn 505
    #define mod 1000000007
    using namespace std;
    typedef long long ll;
    ll n,m;
    ll mp[maxn][maxn];
    ll mx[maxn],mn[maxn];
    ll qn[maxn],qx[maxn];
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            scanf("%lld%lld",&n,&m);
            ll ans=0;
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    scanf("%lld",&mp[i][j]);
                }
            } 
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    mx[j]=-mod;
                    mn[j]=mod;
                }
                for(int j=i;j<=n;j++){
                    for(int k=1;k<=n;k++){
                        mx[k]=max(mx[k],mp[j][k]);
                        mn[k]=min(mn[k],mp[j][k]);
                    } 
                    ll l=1,r=1,f1=1,f2=1,b1=0,b2=0;
                    while(r<=n){
                        while(f1<=b1&&mx[r]>=mx[qx[b1]]) b1--;
                        qx[++b1]=r;
                        while(f2<=b2&&mn[r]<=mn[qn[b2]]) b2--;
                        qn[++b2]=r;
                        if(mx[qx[f1]]-mn[qn[f2]]<=m){
                            ans=max((r-l+1)*(j-i+1),ans);
                            r++;
                            continue;
                        }
                        ans=max((r-l)*(j-i+1),ans);
                        while(l<=r&&mx[qx[f1]]-mn[qn[f2]]>m){
                            l++;
                            while(f1<=b1&&qx[f1]<l) f1++;
                               while(f2<=b2&&qn[f2]<l) f2++;
                        }
                        r++;
                    }
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Redux React-redux 理解
    React ---- 浅谈ReactJs
    javascript --- 鼠标事件
    javaScript --- localStorage 本地存储
    javascript -- 对象(深拷贝、浅拷贝)
    javascript --- 数组输出数组中最大值最小值差值
    Css中未知 div 宽高度,水平垂直居中方法
    Windows下使用NCL(Cygwin模拟Linux环境)
    Qt加载网页(加载浏览器插件)和制作托盘后台运行(南信大财务报账看号)
    OpenGL超级宝典第5版&&GLSL法线变换
  • 原文地址:https://www.cnblogs.com/Lis-/p/11336116.html
Copyright © 2011-2022 走看看