• 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);
    }
    
  • 相关阅读:
    [ZJOI2008]树的统计
    树链剖分总结
    动态主席树(带修改的区间第k大)(树套树)
    实现一个函数输入123456789,输出123,456,789”
    简单的requestAnimationFrame动画
    js的下拉刷新和上拉加载,基于iScroll v4.2.5
    深拷贝和浅拷贝
    js中this的指向
    创建对象的方法
    js继承的方式
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12342222.html
Copyright © 2020-2023  润新知