码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-05-11 22:10:26      阅读:105      评论:0      收藏:0      [点我收藏+]

标签:单调栈


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

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

标签:单调栈

原文地址:http://blog.csdn.net/guard_mine/article/details/45647283

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!