洛谷P1950 长方形(单调栈)

洛谷P1950 长方形(单调栈)一道单调栈的好题啊。。。。。。思路是很奇妙的,对于每个点(i,j),我们可以算它对答案的贡献(即包含它的矩形数量),包含该点的矩形,点的高度为h[j],点右边的高度一定大于等于h[j],左边的高度一定大于h[j]。高有h[j]种方案,底边有(j-lj)*(rj-j)种方案,相乘就是该

大家好,欢迎来到IT知识分享网。洛谷P1950

一道单调栈的好题啊。。。。。。

思路是很奇妙的,对于每个点(i,j),我们可以算它对答案的贡献(即包含它的矩形数量),包含该点的矩形,点的高度为h[j],点右边的高度一定大于等于h[j],左边的高度一定大于h[j]。

高有h[j]种方案,底边有(j – lj) * (rj – j)种方案,相乘就是该点对答案的贡献。

具体步骤:

1.定义 h[j] 为当前行第 j 列可向上延伸多少(如果当前块被图画那么值为0)
2.使用单调栈算出 li 和 ri​ ,分别是 j中左边第一个(从 j​ 开始)不大于 h[j] 的数和右边第一个(从 j 开始)小于 h[j] 的数
3.(j-lj)*(rj-j)*h[j]的值就是每一个点所能组成的矩形的个数。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 char ch;
 4 long long l[1020],r[1020],h[1020],k[1020],n,m,top;
 5 int d[1020][1020];
 6 long long ans;
 7 
 8 void ddzl(){//
 9     top=0;
10     for(int i=m;i>=1;i--){
11         while(top!=0 && h[i]<=h[k[top]]) l[k[top--]]=i; 
12         k[++top]=i;
13     }
14     while(top) l[k[top--]]=0;
15 }
16 
17 void ddzr(){//
18     top=0;
19     for(int i=1;i<=m;i++){
20         while(top!=0 && h[i]<h[k[top]]) r[k[top--]]=i;
21         k[++top]=i;
22     }
23     while(top) r[k[top--]]=m+1;
24 }
25 
26 void work(){
27     ddzl();//求左边第一个小等于的下标 
28     ddzr();//求右边第一个小于的下标 
29     for(int i=1;i<=m;i++)
30         ans+=(i-l[i])*(r[i]-i)*h[i];//累加结果 
31 }
32 
33 int main(){
34     cin>>n>>m;
35     for(int i=1;i<=n;i++)
36     for(int j=1;j<=m;j++){
37         cin>>ch;
38         if(ch=='*') d[i][j]=1;//标记 
39     }
40     for(int i=1;i<=n;i++){ 
41         for(int j=1;j<=m;j++){
42             h[j]++;
43             if(d[i][j]) h[j]=0;//求该列从最上面到j的最大延伸高度 
44         }
45         work();//对每一行累加结果 
46     }
47     cout<<ans;
48 }

(单调栈其实不好想啊,难点在于推公式,公式的意义就是每个点对答案的贡献,公式想到了,自然也能想到用单调栈维护)。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/33505.html

(0)

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信