FZU 非提的救赎(单调栈)
非提的救赎
Accept: 16 Submit: 105
Time Limit: 1000 mSec Memory Limit : 32768 KB
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
bbb
www
2 2
bw
wb
Sample Output
6
2
2
Hint
1<=M,N<=2000题意:求子矩阵全为'w'的个数思路:每一层对这一层的每一个'w',计算能生成的新的矩阵(计算往左往上的贡献),辅助数据结构:单调栈,这样复杂度就是o(N^2) 代码:
#include<stdio.h>
#include<string.h>
#define LL long long
const int N = 2010;
char s[N][N];
int num[N],n,m,top; ///num[i]表示当层第i列往上的'w'的个数
struct node{int x,n;}a; ///我这里处理是值为x的个数为n
node Stack[N]; ///栈
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
LL ans = 0;
memset(num,0,sizeof(num));
for(int i=0;i<n;i++)
{
scanf("%s",s[i]);
top = 0;
LL sum = 0;
for(int j=0;j<m;j++)
{
if(s[i][j]=='b') ///遇到'b',明显前后的矩阵不能连起来,所以分开计算
num[j] = sum = top = 0;
else
{
num[j] ++;
a.x = num[j], a.n = 1;
while(top&&num[j]<=Stack[top].x)
{
///注意这里退栈的时候把所有大于等于num[j]的值全部变成num[j]
sum -= Stack[top].x*Stack[top].n;
a.n += Stack[top].n;
top--; ///退栈
}
sum += a.n*a.x;
ans += sum;
Stack[++top] = a; ///进栈
}
}
}
printf("%I64d\n",ans);
}
return 0;
}View Code




浙公网安备 33010602011771号