HDU计算机学院大学生程序设计竞赛(2015’12)1006 01 Matrix

题意:

有一个n*n(n<=1000)的01矩阵

Q次询问(1000) 每次询问有几个大于等于k的全为一的子矩形

 

从右下角往右上角预处理
每个点有一个r x v
r代表右边有多少连续1
x代表下面有多少连续1
v代表以这个为左上角的矩阵最大是多少
所以v[i][j]= min(r[i][j+1], x[i+1][j],v[i+1][j+1]) +1

r[i][j]=r[i][j+1]+1;

x[i][j]=x[i+1][j]+1;

然后ans[v[i][j]]++

预处理后缀和  O 1 输出

#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
const int N=50005;
int n,k,m;
int s[1005];
int v[1005][1005],r[1005][1005],x[1005][1005],a[1005][1005];
char c[1005];
int main()
{
    int i,j;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        memset(s,0,sizeof(s));
        memset(r,0,sizeof(r));
        memset(x,0,sizeof(x));
        for(i=1; i<=n; i++)
        {
            scanf("%s",c);
            for(j=0;j<n;j++)
                a[i][j+1]=c[j]-'0';
        }
        x[n+1][n]=0;
        r[n][n+1]=0;
        v[n+1][n+1]=0;
        for(i=n; i>=1; i--)
        {
            for(j=n; j>=1; j--)
            {
                if(a[i][j])
                {
                    v[i][j]=min(min(v[i+1][j+1],r[i][j+1]),x[i+1][j]);
                    r[i][j]=r[i][j+1]+1;
                    x[i][j]=x[i+1][j]+1;
                    v[i][j]++;
                }
                else
                    v[i][j]=r[i][j]=x[i][j]=0;
                s[v[i][j]]++;
            }
        }
        for(i=n-1; i>=1; i--)
        {
            s[i]+=s[i+1];
        }
        while(m--)
        {
            scanf("%d",&k);
            cout<<s[k]<<endl;
        }
    }
    return 0;
}

 

  

posted @ 2015-12-26 16:27  Woo95  阅读(250)  评论(0编辑  收藏  举报