P1950 长方形
题意:
在一组点中找出全部的矩形,输出他们的数量。
测试数据:
输入
6 4
…
.***
.…
.**
…*
.***
输出
38
Q1.要如何才能做到不漏不重呢?
统计每一行,以其作为底边所能组成矩形的个数。
总和为方案数。
在测试数据中,每一行的矩形个数分别为:
10
2
6
4
10
6
总和为38。
Q2.如何统计每一行,以其作为底边的矩形数?
- 定义 hi 为当前行第 i 列可向上延伸多少(即有多少为图画的块,如果当前块被图画那么值为0)
- 使用单调栈算出 li 和 ri ,分别是 h 中左边第一个(从 hi 开始)不大于 hi 的数和右边第一个(从 hi 开始)小于 hi 的数
- (i-li)*(ri-i)*hi的值就是每一个点所能组成的矩形的个数。
即:包含该点的矩形,点的高度为h,点右边的高度一定大于等于h,左边的高度一定大于h。
单调栈
顾名思义,栈内的元素都是单调的。
当一个元素准备入栈时,将所有大于/等于/小于它的元素全部pop(),
实现一些操作,
最后将该元素push进去。
计算ri:
void ddzr(){
stack<int > sst;
int i;
h[m+1]=-1;//为了将栈内元素全部输出
for(i=1;i<=m+1;i++){
while(sst.empty()==0&&h[sst.top()]>h[i])
r[sst.top