CREC01 - Đếm hình chữ nhật trên bảng 0-1

Tác giả: happyboy99x

Ngôn ngữ: C++

#include<cstdio>

const int N = 1005;

/* Stack */
int stack[N], topS;
void init() { topS = 0; }
int top() { return stack[topS-1]; }
int pop() { return stack[--topS]; }
void push(const int &x) { stack[topS++] = x; }
/* End of Stack */

int m, n, f[N][N], left[N];
long long dp[N];
char a[N][N];
/* f[y][x] = k <=> a[y..y+k-1][x] = 11..., k max */

void enter() {
	scanf("%d%d",&m,&n);
	for(int i = 0; i < m; ++i)
		scanf("%s", a[i]);
}

void calcF() {
	for(int j = 0; j < n; ++j)
		for(int i = m-1; i >= 0; --i)
			f[i][j] = a[i][j] == 0x31 ? f[i+1][j] + 1 : 0;
}

void solve() {
	long long res = 0;
	for(int i = 0; i < m; ++i) {
		left[0] = 0; init();
		for(int j = 1; j < n; ++j)
			if(f[i][j] > f[i][j-1]) left[j] = j, push(j-1);
			else {
				while(topS && f[i][j] <= f[i][top()]) pop();
				left[j] = topS ? top() + 1 : 0;
			}
		for(int j = 0; j < n; ++j) res += dp[j] = (left[j] == 0 ? 0 : dp[left[j]-1]) + (j - left[j] + 1) * f[i][j];
	}
	printf("%lld\n", res);
}

int main() {
	enter();
	calcF();
	solve();
	return 0;
}

Download