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;
}