仿佛是第二次做这个题啦?
上次不知道怎么 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 ",ans); return 0; }