cf Maximum Subrectangle

http://codeforces.com/contest/1060/problem/C

 

矩形中的和只和n,m数列在这上面的分别的和有关。比如1,2,3和7,8,9交叉形成的和=(1+2+3)*(7+8+9)=144。

而两个的交叉是分别的选择,无相互影响。

那么,策略就是,我们先找到对于数列n来说的一个目标数列n_sum[],n_sum[i]记录着n中所有连续长度为i的段中,和最小是多少。举例来说:n=[3,4,2,2],那么n_sum=[0,2,4,8,11],其中下标3的数是8,代表n中长为3的连续子序列中最小和是8。

怎么得到的后面解释,先把有这个n_sum和m_sum为前提。注意这两个数列中的数值是递增的。

有了n_sum和m_sum,n_sum的每个下标i,找到m_sum[j]*n_sum[i]<x就行了。因为两个数列中的数值是递增的,用双指针记录位置,可用o(n)做完。这样等于穷举所有长度搭配的可能。每次找到后,用ans=max(ans,i*j)就行了。

 

至于怎么找每个长度的最小和,先复制n中内容到temp,先找长度1,等于min(n),然后每次temp[i]=n[i]+temp[i+1]就逐次累加长度了。这是o(n^2)复杂度的。

python太慢过不了,用c++重写了一遍,花了一个半小debug的问题竟然又是出在爆int上,哎~

int是32bit 最大10^10

python版:

n, m = [int(x) for x in input().split()]
ns = [int(x) for x in input().split()]
ms = [int(x) for x in input().split()]
k = int(input())


def getlen(arr):
    ans = [0]
    start = arr[:]
    ans.append(min(arr))
    for l in range(2, len(arr) + 1):
        minn = 10**16
        for i in range(len(arr) - l + 1):
            start[i] = arr[i] + start[i + 1]
            minn = min(minn, start[i])
        ans.append(minn)
    return ans

nl=getlen(ns)
ml=getlen(ms)


j=0
ans=0
for i in reversed(range(n+1)):
    while j<m+1 and ml[j]*nl[i]<=k:
        j+=1
    ans=max(ans,i*(j-1))

print(ans)
View Code

 

c++版:

#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
vector<ll> getlen(ll* a,ll l){
    vector<ll> ans;
    ans.push_back(0);
    ll start[l];
    memcpy(start, a, l*sizeof(ll));
    ll minn=INT_MAX;
    for(ll i =0;i<l;i++)
        minn=min(minn,start[i]);
    ans.push_back(minn);
    for(ll k=2;k<=l;k++){
        minn=INT_MAX;
        for(ll i=0;i<=l-k;i++){
            start[i]=a[i]+start[i+1];
            minn=min(minn,start[i]);
        }
        ans.push_back(minn);
    }
    return ans;
}

int main(int argc, char** argv)
{
    ll n,m;
    cin>>n>>m;
    ll ns[n];
    ll ms[m];
    for(ll i=0;i<n;i++){
        cin>>ns[i];
    }
    for(ll i=0;i<m;i++){
        cin>>ms[i];
    }
    ll k;
    cin>>k;

    vector<ll> nl=getlen(ns,n);
    vector<ll> ml=getlen(ms,m);
    ll ans=0;
    ll j=1;
    for(ll i=n;i>0;i--){
        while(j<m+1 && ml[j]*nl[i]<=k)j++;
        ans=max(ans,i*(j-1));
    }
    cout<<ans;
    return 0;
}

 

posted @ 2018-10-05 01:21  Cloud.9  阅读(357)  评论(0编辑  收藏  举报