大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。遥想公瑾当年,小乔初嫁了,雄姿英发。羽扇纶巾,谈笑间,樯橹灰飞烟灭。故国神游,多情应笑我,早生华发。人生如梦,一尊还酹江月。

CF1060C题解

为了摆脱小凯的阴影,我开始刷CF上的思维题

模拟

由乘法分配律,有\(\sum_{i=x1}^{x2}\sum_{j=y1}^{y2}c_{i,j}=\sum_{i=x1}^{x2}\sum_{j=y1}^{y2}a_i*b_j=\sum_{i=x1}^{x2}a_i*\sum_{j=y1}^{y2}b_j\)

故问题转变为选取 a,b 的两个字段,使其乘积 ≤ x,且面积最大

刚开始的思路是可以\(n^2\)枚举a的所有区间,对于每个区间,若权值和为v,则在权值 <= x/v 的区间中选取长度最长的,可以用树状数组+离散化 or 动态开点权值线段树维护,复杂度\(O(N^2logN)\)

后来看了题解有一种更简单的思路,若区间长度一定,则权值越小越好,故记录长度为i的最小权值,复杂度可降至\(O(N^2)\)

#include<bits/stdc++.h>
using namespace std;

#define go(i,a,b) for(int i=a;i<=b;++i)
#define com(i,a,b) for(int i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof(a))
#define fo(i,a) for(int i=0;i<a;++i)
#define il inline
#define int long long

const int inf=0x3f3f3f3f,N=2e3+10;

int n,m,a[N],b[N],lim,f[N],g[N];

il void read(int &x){
	x=0;char c=getchar(),f=1;
	while(!isdigit(c)){ if(c=='-') f=-1; c=getchar(); }
	while(isdigit(c)){ x=x*10+c-'0'; c=getchar(); }
	x*=f;
}
il void gmin(int &x,int y){
	x=x<y?x:y;
}

signed main(){
	//freopen("input.txt","r",stdin);
	read(n),read(m);
	go(i,1,n) read(a[i]),a[i]+=a[i-1];
	go(i,1,m) read(b[i]),b[i]+=b[i-1];
	read(lim);
	mem(f,0x3f),mem(g,0x3f);
	go(i,1,n)
		go(j,i,n)
			gmin(f[j-i+1],a[j]-a[i-1]);
	go(i,1,m)
		go(j,i,m)
			gmin(g[j-i+1],b[j]-b[i-1]);
	int ans=0;
	go(i,1,n)
		go(j,1,m)
			if(f[i]*g[j]<=lim) 
				ans=max(ans,i*j);
	cout<<ans;
	return 0;
}
posted @ 2019-11-01 16:24  White_star  阅读(156)  评论(0编辑  收藏  举报
}