[COCI2015]BNE 最大全1子矩阵

题意

你有一个1000*1000的矩阵,现在定义一个矩阵 $A_{x,y} $ 是酷的当且仅当 a 1 , 1 + a x , y < = a x , 1 + a 1 , y a_{1,1}+a_{x,y}<= a_{x,1}+a_{1,y} a1,1+ax,y<=ax,1+a1,y x > 1 , y > 1 x>1,y>1 x>1,y>1 条件成立时。 而一个矩阵是非常酷的当且仅当它的所有子矩阵都是酷的。现在问你,非常酷的矩阵的最大的元素个数有多少。

做法

我们证明一下,假设有如下图,两边的矩阵都是单位酷矩阵(也是非常酷的矩阵)了,那么我们会有条件

a + d < = c + b a+d<=c+b a+d<=c+b c + f < = e + d c+f<=e+d c+f<=e+d

我们将上面两个公式相加,会得到 a + f < = b + e a+f<=b+e a+f<=b+e,即对于一个新的矩阵来说,也是非常酷的。

那么我们就可以先算出所有2*2的子矩阵是否为酷的,如果是则标记为1,否则标记为0,就可以把问题转化成为一个求最大全1矩阵的问题。

在这里插入图片描述

然后就是板子的事情了。

代码

#include<cstdio>
#include<algorithm>
#define fi first
#define se second
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn=1005;
int n,m,b[maxn][maxn],sum[maxn][maxn];
int a[maxn][maxn],ma[maxn],ans;
int read(){
    int ans=0; char last=' ',ch=getchar();
    while(ch<'0' || ch>'9')last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans; return ans;
}
int s[maxn],top,L[maxn],R[maxn];
void fin(int r){
    top=0; s[0]=0;
    sum[r][m+1]=0;
    for(int i=1;i<=m+1;i++){
        int p=s[top];
        while(sum[r][i]<sum[r][p]){
            R[p]=i; top--;
            p=s[top];
        }
        L[i]=p;
        s[++top]=i;
    }
    rep(i,1,m){
        if(sum[r][i]) ans=max(ans,(sum[r][i]+1)*(R[i]-L[i]));
    }

}
int main(){
    n=read(),m=read();

    rep(i,1,n) rep(j,1,m) a[i][j]=read();
    rep(i,1,n-1) rep(j,1,m-1){
        if(a[i][j]+a[i+1][j+1]<=a[i+1][j]+a[i][j+1]) b[i][j]=1;
    }
    rep(i,1,n-1) rep(j,1,m-1) if(b[i][j]) sum[i][j]=sum[i-1][j]+1;
    m--;
    rep(i,1,n-1) fin(i);

    printf("%d\n",ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值