标签:bzoj3039 玉蟾宫 hdu1505 city game 最大01子矩阵
转载请注明出处:http://blog.csdn.net/vmurder/article/details/42884845
首先我们可以用单调栈每行扫一遍,维护一个点向上下左右各能延伸多长。
当然,这是可以做的,也是很恶心的。
我们可以每行扫一遍,维护每个点当前的[列高度]时能向左向右的最大延伸距离。
当然,某个点可能降低一点高度,就会更宽,结果更优,但是显然既然存在这种结果,那么其它列一定可以代劳。
呃。所以每行扫一遍,然后记录这行每个节点以最大高度能向左向右延伸的最大距离就好了。
这道题思想上可以用单调栈来做,但是我写了一个类似前缀和或者区间覆盖并查集或者什么玩意的一个东西。
啊,看起来是个while循环,但是可以证线性的~。嗯,均摊分析全局分析神马的。
算法基于不停延伸的思想。
怎么说呢,就是每个点的当前高度都有一个向左/向右延伸距离,然后既然这个点满足,那么这个段也一定满足
(a<=b b<=c 则a<=c)
然后就跳过这个段,check下一段。
不要去分析每一个都需要几次,要分析每一个对其它的贡献,然后随便YY就能证线性了。
代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 1010 using namespace std; char s[3]; int d[N],l[N],r[N]; int n,m,ans; int main() { int i,j,k; memset(d,0,sizeof d); scanf("%d%d",&n,&m); for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { l[j]=r[j]=j; scanf("%s",s); if(s[0]=='F')d[j]++; else d[j]=0; } for(j=1;j<=m;j++)if(d[j])while(d[j]<=d[l[j]-1])l[j]=l[l[j]-1]; for(j=m;j>=1;j--)if(d[j])while(d[j]<=d[r[j]+1])r[j]=r[r[j]+1]; for(j=1;j<=m;j++)ans=max(ans,(r[j]-l[j]+1)*d[j]); } printf("%d\n",ans*3); return 0; }
【BZOJ3039】玉蟾宫/【HDU1505】【POJ1964】City Game 最大01子矩阵
标签:bzoj3039 玉蟾宫 hdu1505 city game 最大01子矩阵
原文地址:http://blog.csdn.net/vmurder/article/details/42884845