Codeforces 131 F. Present to Mom

問題

nxmマスのグリッドにおいて、「星」とは

 1
111
 1

のような1の並びを言う。星は互いに一部が重なっていてもよい。

nxmマス長方形の部分長方形で、星をk個以上含むものはいくつあるか、求めよ。

制約条件

n,m≦500

方針

部分長方形の上下を適当に決め付ける。
その上で右方向にしゃくとりをして、k個以上星を含むような長方形をO(m)で求める。


しゃくとりをする際に、一列にいくつ星が含まれるかをO(1)で求める必要がある。
これは前処理であらかじめ累積和を計算しておくことでできる。

ソースコード

int n,m,k;
bool star[600][600];
int sum[600][600];
char in[600][600];

void run()
{
	cin>>n>>m>>k;
	rep(i,n)cin>>in[i];
	rep(i,n)rep(j,m){
		if(in[i][j]=='1'&&in[i+1][j]=='1'&&in[i+2][j]=='1'&&
			j&&in[i+1][j-1]=='1'&&in[i+1][j+1]=='1')star[i][j]=1;
	}
	ll ans=0;
	rep(i,n)rep(j,m)sum[i+1][j+1]=star[i][j]+sum[i][j+1]+sum[i+1][j]-sum[i][j];

	rep(a,n)for(int b=a+3;b<=n;b++){
		int l=0,r=2,cnt=0;
		for(;l<m;l++){
			while(r<=m&&cnt<k){
				r++;
				cnt+=sum[b-2][r-1]-sum[a][r-1]-(sum[b-2][r-2]-sum[a][r-2]);
			}
			if(cnt<k||r>m)break;
			ans+=m-r+1;
			cnt-=sum[b-2][l+2]-sum[a][l+2]-(sum[b-2][l+1]-sum[a][l+1]);
		}
	}
	cout<<ans<<endl;
}