【BZOJ3039】玉蟾宫/【HDU1505】【POJ1964】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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值