洛谷P1950
P1950 长方形
绿题,比赛依旧暴力吧,我算是发现了,绿题就是我智商上限了
这题其实和P4147一样需要借助悬线,不同点在于一个求组合数,一个求最大值
点击查看代码
#include<bits/stdc++.h>
#define MAXN 1010
using namespace std;
char ch[MAXN][MAXN];
int n, m, top;
int h[MAXN], l[MAXN], r[MAXN], st[MAXN];
long long ans;
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) cin >> ch[i][j];
}
for(int i = 1; i <= n; i++) {//以行为单位进行处理
for(int j = 1; j <= m; j++) h[j] = ch[i][j] == '*' ? 0 : h[j] + 1;//h数组的处理有点像悬线
top = 0;//重置单调栈,处理r数组
for(int j = 1; j <= m; j++) {
while(top > 0 && h[j] < h[st[top]]) {
r[st[top]] = j;
top--;
}
top++;
st[top] = j;
}
while(top > 0) {
r[st[top]] = m + 1;
top--;
}
//r[i]为该列右边第一个满足h值小于h[i]的下标号
//没有找到就是m+1
//这里自然是使用单调栈进行处理
top = 0;
for(int j = m; j >= 1; j--) {
while(top > 0 && h[j] <= h[st[top]]) {
l[st[top]] = j;
top--;
}
top++;
st[top] = j;
}
while(top > 0) {
l[st[top]] = 0;
top--;
}
//l[i]为该列左边第一个满足h值小于等于h[i]的下标号
//没有找到就是0
//处理方法与r数组类似
for(int j = 1; j <= m; j++) {
ans += (j - l[j]) * (r[j] - j) * h[j];
}
//想要理解这一部分建议参考《深入浅出(进阶)》P014 图1-6
}
cout << ans;
return 0;
}

浙公网安备 33010602011771号