码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #513 by Barcelona Bootcamp (rated, Div. 1 + Div. 2) C. Maximum Subrectangle

时间:2018-10-07 00:03:48      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:昨天   img   .com   com   fill   sync   二分   结束   return   

昨天做的,今天才想起来,要写个博客,记一下这种矩阵题怎么做。

首先我没有意识到,每个方向上累和,得到两个累和数组,它们的子序列之积,就是子序列对应的矩形区域范围内所有数字之和,说起来有点抽象,但是举个栗子吧,技术分享图片

就像用例里面的这张提示图,横坐标我选子列2,3,则和为5,纵坐标我选子列1,2,则和为3。那么3和5,乘积为15,而把矩阵中对应区域的和相加,也是15,。则这个问题就容易了:只需要枚举一维数组就可以了。但是,如果枚举一维数组,那岂不是要做一个四重循环?其实不然。

题目要我们获得一个不大于限定数值的最大值,在此之前,我们需要对其中一个序列做一个预处理:二重循环枚举所有子列,计算对应子列长度下的最小子列和(最小,才能保证取更多的点,也就是更长的长度,也就是更大的面积)。之后,可以选定两个中的另一个序列,用一个二重循环得到子列和,再用限定数值除以这个和,得到一个目标值。之后,在最初预处理得到的数组中二分查找目标值,返回大于它的第一个值,也就是用upper_bound,求出之后长度减一即可,这样保证长度最长。最后,用查找得到的长度和当前子列长度相乘,得到的结果始终取最大值,循环结束之后,就是答案。

#include <bits/stdc++.h>
#define N 2005
#define INF 0x7fffffff
using namespace std;
typedef long long ll;
int a[N],b[N];
ll ma[N],x;
int main()  {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,m,ans=0;
    fill(ma,ma+N,INF);
    cin>>n>>m;
    for (int i=1;i<=n;i++)  {cin>>a[i];a[i]=a[i-1]+a[i];}
    for (int i=1;i<=m;i++)  {cin>>b[i];b[i]=b[i-1]+b[i];}
    cin>>x;
    for (int i=1;i<=n;i++)  {
        for (int j=i;j<=n;j++)  {
            ll tsm=a[j]-a[i-1];
            int len=j-i+1;
            ma[len]=min(ma[len],tsm);
        }
    }
    for (int i=1;i<=m;i++)  {
        for (int j=i;j<=m;j++)  {
            ll sc=x/(b[j]-b[i-1]);
            int len=j-i+1;
            int mxa=upper_bound(ma+1,ma+n+1,sc)-ma-1;
            ans=max(ans,len*mxa);
        }
    }
    cout<<ans<<endl;
    return 0;
}

Codeforces Round #513 by Barcelona Bootcamp (rated, Div. 1 + Div. 2) C. Maximum Subrectangle

标签:昨天   img   .com   com   fill   sync   二分   结束   return   

原文地址:https://www.cnblogs.com/yichuan-sun/p/9749030.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!