洛谷 P1950 长方形_NOI导刊2009提高(2)

题面

 

仿佛是第二次做这个题啦?

上次不知道怎么 O(N^3)卡过去的,真是牛逼。。。。

这次做是正经的 O(N^2)。

我们考虑只在一个长方形的右下角统计到它,然后画一画图就可以发现,以一个点为右下角的长方形的数量,等于 把这一行每个点的权值看成能向上最多延伸的点的数量 ,然后由这些权值构成的单调(上升)栈的Σh[s[i]](s[i]-s[i-1])       (也就是单调栈画到二维平面的图形面积),因为这个值正好是所有左端点可以取到的位置的数量。

 

恩,然后直接跑单调栈维护就好了,O(N^2)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1005;

int h[N],n,m,now,s[N],tp;
char ch;
ll ans;

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;tp=now=0,i++)
	    for(int j=1;j<=m;j++){
	    	ch=getchar();
	    	while(ch!='.'&&ch!='*') ch=getchar();
	    	h[j]=ch=='.'?h[j]+1:0;
	    	
	    	while(tp&&h[j]<=h[s[tp]]) now-=h[s[tp]]*(s[tp]-s[tp-1]),tp--;
	    	s[++tp]=j,now+=h[j]*(s[tp]-s[tp-1]); 
	    	
	    	ans+=(ll)now;
		}
	printf("%lld\n",ans);
	return 0;
}

  

posted @ 2019-08-04 10:34  蒟蒻JHY  阅读(187)  评论(0编辑  收藏  举报