fzu2190---非提的救赎 (单调栈)

来源:互联网 发布:淘宝买到假货怎么投诉 编辑:程序博客网 时间:2024/06/05 08:04

Problem Description

正如你所知道从前有一个人叫s_sin,她拥有着坐拥三千舰狼的梦想!然而天不遂人愿当她踏进hentai collection的大门之后,现实让她领略到了无情。身为一个坚强的妹子,她知道即使出门大破,即使十一连抽全是R,也要坚信着“玄不救非,氪不改命”,而自己是一个欧白这样最初的信仰!

有一天s_sin率领着她的舰狼们到达了某海峡,以一个N*M的矩阵表示,每一个元素为w或者b。其中b为暗礁,暗礁上是不允许有舰狼存在的。而s_sin也相信着一个道理,那就是只有把她的舰狼们组成矩形,她才能有足够的信仰在打败了最终boss之后捞到心仪的新舰狼。请问s_sin有多少种获取足够信仰的方法?(即在N*M的矩阵中有多少个全部由w组成的子矩形)
Input

输入第一行为一个正整数N,M表示有N行M列的矩阵。

接下来N行每行有M个字母为b或者w,如描述中所述。
Output

求N*M的矩阵中有多少个全部由w组成的子矩形。
Sample Input
2 3
bbb
www
2 2
bw
wb
Sample Output
6
2
Hint
1<=M,N<=2000
Source
福州大学第十二届程序设计竞赛

一行行考虑,单调栈维护,得到每一列最远可以往左边扩展到的位置
那么height[j] * len就是由这一列产生的,但是要注意,前面比这一列矮的列,向右扩展到这一列,其实还有矩形,所以要把那一列产生的矩形加上去

/*************************************************************************    > File Name: fzu2190.cpp    > Author: ALex    > Mail: zchao1995@gmail.com     > Created Time: 2015年05月10日 星期日 21时43分44秒 ************************************************************************/#include <functional>#include <algorithm>#include <iostream>#include <fstream>#include <cstring>#include <cstdio>#include <cmath>#include <cstdlib>#include <queue>#include <stack>#include <map>#include <bitset>#include <set>#include <vector>using namespace std;const double pi = acos(-1.0);const int inf = 0x3f3f3f3f;const double eps = 1e-15;typedef long long LL;typedef pair <int, int> PLL;static const int N = 2010;char mat[N][N];int height[N][N];PLL Stack[N];int Top;int L[N];int sum[N];int main() {    int n, m;    while (~scanf("%d%d", &n, &m)) {        for (int i = 1; i <= n; ++i) {            scanf("%s", mat[i] + 1);        }        memset(height, 0, sizeof(height));        for (int i = 1; i <= m; ++i) {            height[i][0] = 0;            for (int j = 1; j <= n; ++j) {                height[i][j] = height[i][j - 1];                if (mat[j][i] == 'w') {                    ++height[i][j];                }                else {                    height[i][j] = 0;                }            }        }        LL ans = 0;        for (int i = 1; i <= n; ++i) {            Top = 0;            for (int j = m; j >= 1; --j) {                L[j] = j;                sum[j] = 0;            }            sum[0] = 0;            for (int j = m; j >= 1; --j) {                if (!Top) {                    Stack[++Top] = make_pair(height[j][i], j);                }                else {                    while (Top) {                        PLL u = Stack[Top];                        if (u.first <= height[j][i]) {                            break;                        }                        L[u.second] = j + 1;                        --Top;                    }                    Stack[++Top] = make_pair(height[j][i], j);                }            }            while (Top) {                PLL u = Stack[Top];                --Top;                L[u.second] = 1;            }            for (int j = 1; j <= m; ++j) {                if (!height[j][i]) {                    continue;                }                int l = L[j];                sum[j] = (LL)height[j][i] * (j - l + 1);                if (l - 1 >= 1) {                    sum[j] += sum[l - 1];                }                ans += sum[j];            }        }        printf("%lld\n", ans);    }    return 0;}
0 0
原创粉丝点击