zoukankan      html  css  js  c++  java
  • JOI2017FinalC JOIOI 王国

    Link
    显然答案具有单调性,所以我们考虑二分答案。
    由题可知,JOI和IOI的分界线是单调的,即要么是从左上到右下,要么是从左下到右上。
    并且我们知道,最大值和最小值肯定不能在同一个省里。
    所以要么是最大值(mx)在左边的省里,要么是最小值(mn)在左边的省里。
    所以对于一个二分出来答案(lim),我们需要满足(mx)所在的省中的最小值大于等于(mx-lim)(mn)所在省中的最大值小于等于(mn+lim)
    所以我们枚举最大值的两种情况(一种在左一种在右),再枚举分界线的两种情况。总共四种情况,有一种情况可以满足要求,那么这个(lim)就是可以满足的。
    现在考虑如何check。
    比如对于最大值在左边,分界线从左上到右下的情况。这种情况左边的最小值必须大于等于(mx-lim)
    我们(O(n^2))贪心地求出每一行最多能往右扩展到哪里。
    然后再从下往上,计算每一行的边界线(下面一行的分界线和这一样最多能扩展到地方的最小值)。
    这样边界线以左的部分显然会满足最小值大于等于(mx-lim)并且边界线单调。
    所以我们只需要(O(n))检查右边是否存在大于(mn+lim)的数即可。
    总体而言,我们只需要预处理出每一行前缀后缀的最大值最小值即可。

    #include<bits/stdc++.h>
    #define mid ((l+r)>>1)
    using namespace std;
    int read(){int x=0;char c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x;}
    int min(int a,int b){return a<b? a:b;}
    int max(int a,int b){return a>b? a:b;}
    const int N=2007,inf=1e9+7;
    int t[N],a[N][N],pmx[N][N],smx[N][N],pmn[N][N],smn[N][N],n,m,lim,mn=inf,mx=-inf,mxlim,mnlim;
    void mncal(){for(int i=1,j;i<=n;++i)for(t[i]=0,j=1;j<=m;++j)if(pmx[i][j]<=mnlim)t[i]=j;else break;}
    void mxcal(){for(int i=1,j;i<=n;++i)for(t[i]=0,j=1;j<=m;++j)if(pmn[i][j]>=mxlim)t[i]=j;else break;}
    int c1(){mncal();for(int i=n,p=m;i;--i){p=min(p,t[i]);if(smn[i][p+1]<mxlim) return 0;}return 1;}
    int c2(){mxcal();for(int i=n,p=m;i;--i){p=min(p,t[i]);if(smx[i][p+1]>mnlim) return 0;}return 1;}
    int c3(){mncal();for(int i=1,p=m;i<=n;++i){p=min(p,t[i]);if(smn[i][p+1]<mxlim) return 0;}return 1;}
    int c4(){mxcal();for(int i=1,p=m;i<=n;++i){p=min(p,t[i]);if(smx[i][p+1]>mnlim) return 0;}return 1;}
    int main() 
    {
        n=read(),m=read();int i,j,l,r,ans;
        for(i=1;i<=n;smn[i][m+1]=pmn[i][0]=inf,++i) for(j=1;j<=m;++j) a[i][j]=read(),mx=max(mx,a[i][j]),mn=min(mn,a[i][j]);
        for(i=1;i<=n;++i)
        {
    	for(j=1;j<=m;++j) pmx[i][j]=max(a[i][j],pmx[i][j-1]),pmn[i][j]=min(a[i][j],pmn[i][j-1]);
    	for(j=m;j;--j) smx[i][j]=max(a[i][j],smx[i][j+1]),smn[i][j]=min(a[i][j],smn[i][j+1]);
        }
        for(l=0,r=mx-mn;l<=r;) lim=mid,mxlim=mx-lim,mnlim=mn+lim,(c1()||c2()||c3()||c4()? (ans=mid,r=mid-1):(l=mid+1));
        printf("%d
    ",ans);
    }
    
  • 相关阅读:
    ABAP-FI-Redirection of read accesses from ANEA to FAAV_ANEA failed
    招聘
    五分钟教你在长沙如何找到靠谱的驾校和教练(长沙找驾校)
    数组哪些方法能改变原数组,以及循环改变数组的情况
    FXGL游戏开发-JavaFX游戏框架
    tempermonkey.d.ts | 油猴函数类型
    post导出文件
    mescroll.js 使用
    查看托管应用池用法
    IDEA配置
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12342222.html
Copyright © 2011-2022 走看看