Codeforces Round #513 by Barcelona Bootcamp (rated, Div. 1 + Div. 2) C. Maximum Subrectangle
阿新 • • 發佈:2018-10-07
提示 tsm 最小 n+1 數值 cin tdi ted 子序列
昨天做的,今天才想起來,要寫個博客,記一下這種矩陣題怎麽做。
首先我沒有意識到,每個方向上累和,得到兩個累和數組,它們的子序列之積,就是子序列對應的矩形區域範圍內所有數字之和,說起來有點抽象,但是舉個栗子吧,
就像用例裏面的這張提示圖,橫坐標我選子列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