[ABC311G] One More Grid Task

Problem Statement

There is an N×M grid, where the square at the i-th row from the top and j-th column from the left has a non-negative integer Ai,j written on it.
Let us choose a rectangular region R.
Formally, the region is chosen as follows.

  • Choose integers lx,rx,ly,ry such that 1lxrxN,1lyryM.
  • Then, square (i,j) is in R if and only if lxirx and lyjry.

Find the maximum possible value of f(R)= (the sum of integers written on the squares in R) × (the smallest integer written on a square in R).

Constraints

  • All input values are integers.
  • 1N,M300
  • 1Ai,j300

这题有一万种做法。

枚举最小值 x,现在要求一个权值和最大的矩阵,满足所有数的最小值不小于 x

si,j(i,j) 往上最多有多少个数是不小于 x 的,然后对于某一行的某个区间,他往上能有多高取决于这个区间中所有数的最小值。

区间的最小值? 考虑单调栈求出这一行下一个和上一个比 vi,j 小的区间,然后在这段区间之间的高度就取决于 vi,j 的高度,二位前缀和统计即可。

#include<bits/stdc++.h>
using namespace std;
const int N=305;
typedef long long LL;
int n,m,st[N],s[N][N],ls[N],nx[N],tp,a[N][N],v[N][N];
LL p[N][N],ans;
LL ask(int ax,int ay,int bx,int by)
{
	return p[bx][by]+p[ax-1][ay-1]-p[ax-1][by]-p[bx][ay-1];
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			scanf("%d",a[i]+j),p[i][j]=p[i][j-1]+a[i][j];
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			p[i][j]+=p[i-1][j];
	for(int i=1;i<=300;i++)
	{
		for(int j=1;j<=n;j++)
		{
			for(int k=1;k<=m;k++)
			{
				if(a[j][k]>=i)
					v[j][k]=v[j-1][k]+1;
				else
					v[j][k]=0;
			}
		}
		for(int j=1;j<=n;j++)
		{
			for(int k=1;k<=m;k++)
				ls[k]=0,nx[k]=m+1;
			for(int k=1;k<=m;k++)
			{
				while(tp&&v[j][st[tp]]>v[j][k])
					nx[st[tp--]]=k;
				st[++tp]=k;
			}
			tp=0;
			for(int k=m;k;k--)
			{
				while(tp&&v[j][st[tp]]>v[j][k])
					ls[st[tp--]]=k;
				st[++tp]=k;
			}
			for(int k=1;k<=m;k++)
				ans=max(ans,1LL*i*ask(j-v[j][k]+1,ls[k]+1,j,nx[k]-1));
			
		}
	}
	printf("%lld",ans);
}

posted @   灰鲭鲨  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示