BZOJ 1127 [POI2008]KUP 最大子矩阵

来源:互联网 发布:上网便宜的手机卡知乎 编辑:程序博客网 时间:2024/06/10 18:31

题意:链接

方法:最大子矩阵

解析:

先考虑1*n的情况,如果有在目标区间内的直接输出。

否则找是否存在一个区间即可。

然后能否推广呢?

可以的。

如果元素有在目标区间的值的话,直接输出即可。

否则的话我们将大于2*k的点看作坏点。

则我们只要扫极大子矩阵再进行验证即可。

考虑如何验证总和满足目标区间的极大子矩阵。

如果是1*n的情况,因为所有的元素都小于k。

所以必定有一个前缀的和是在目标区间内的。

所以我们只需要缩y2即可。

如果是正常的矩阵的话,上下两行一定存在一行满足和小于k,干掉这一行后判断矩阵和是否满足目标区间,不满足则递归,满足则输出。

代码:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define N 2010using namespace std;typedef long long ll;int k,n;ll sum[N][N];ll a[N][N];int le[N][N];int ri[N][N];int h[N][N];ll getsum(int x1,int y1,int x2,int y2){    return sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1];}void print(int x1,int y1,int x2,int y2){    while(getsum(x1,y1,x2,y2)>2*k)    {        if(x1==x2)y2--;        else if(getsum(x1+1,y1,x2,y2)>=k)x1++;        else x2--;    }    printf("%d %d %d %d\n",y1,x1,y2,x2);    exit(0);}int main(){    scanf("%d%d",&k,&n);    for(int i=1;i<=n;i++)    {        for(int j=1;j<=n;j++)        {            scanf("%lld",&a[i][j]);            if(a[i][j]>=k&&a[i][j]<=2*k)            {                printf("%d %d %d %d\n",j,i,j,i);                return 0;            }            sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+a[i][j];        }    }    for(int i=1;i<=n;i++)    {        for(int j=1;j<=n;j++)        {            if(a[i][j]>2*k)                le[i][j]=0;            else le[i][j]=le[i][j-1]+1;        }        for(int j=n;j>=1;j--)        {            if(a[i][j]>2*k)                ri[i][j]=0;            else ri[i][j]=ri[i][j+1]+1;         }    }    for(int i=1;i<=n;i++)    {        for(int j=1;j<=n;j++)        {            if(a[i][j]<=2*k&&a[i-1][j]<=2*k&&i!=1)            {                h[i][j]=h[i-1][j]+1;                le[i][j]=min(le[i-1][j],le[i][j]);                ri[i][j]=min(ri[i-1][j],ri[i][j]);            }        }    }    for(int i=1;i<=n;i++)    {        for(int j=1;j<=n;j++)        {            if(a[i][j]<=2*k)            {                int tmp=getsum(i-h[i][j],j-le[i][j]+1,i,j+ri[i][j]-1);                if(tmp>=k)                    print(i-h[i][j],j-le[i][j]+1,i,j+ri[i][j]-1);            }        }    }    puts("NIE");} 
1 0
原创粉丝点击