Fzu-2190 非提的救赎 (单调栈)

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 3bbbwww2 2bwwb

Sample Output

62

Hint

1<=M,N<=2000




分析:单调栈的应用,计算每个w对答案的贡献。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
struct thing
{
	long long n,x;
} stack[2001];
long long n,m,t,sum,ans,num[2001];
char c;
int main()
{
	cin.sync_with_stdio(false);
	while(cin>>n>>m)
	{
		memset(num,0,sizeof(num));
		ans = 0;
		for(int i = 1;i <= n;i++)
		{
			sum = t = 0; 
			for(int j = 1;j <= m;j++)
			{
				cin>>c;
				if(c == 'b') num[j] = t = sum = 0;
				else
				{
					num[j]++;
					thing u;
					u.x = num[j];
					u.n = 1;
					while(t && stack[t].x >= u.x)
					{
						sum -= stack[t].x*stack[t].n;
						u.n += stack[t].n;
						t--;	
					} 	
					sum += u.x*u.n;
					stack[++t] = u;
					ans += sum; 
				}
			}
		}
	    cout<<ans<<endl;
	}
} 



你可能感兴趣的:(ACM,好题)