题意
给定一个
(n,m,k)
的长方体,沿
x
轴每一层
题解
如果确定了
max
,那么显然边长为
max
的正方体只用一个,其他区域都用边长为1的填充是更优的。同时,如果一个边长为
max
的正方体放的进去,
max−1
的正方体肯定也能放的进去。如果能求得
max
的最大值就可以通过
O(n)
枚举
max
来求得答案了。
那么如何求得
max
的最大值呢?根据
max
合法的单调性,可以考虑二分。由于
n≤105
,应当考虑
O(n)
的检验使得复杂度为
O(nlogn)
。
如何进行
O(n)
检验一个数
M
是否合法呢?一开始我用4个set维护当前区间(区间长度为
代码
/// by ztx
/// blog.csdn.net/hzoi_ztx
#include <bits/stdc++.h>
#define Rep(i,l,r) for(i=(l);i<=(r);i++)
#define rep(i,l,r) for(i=(l);i< (r);i++)
#define Rev(i,r,l) for(i=(r);i>=(l);i--)
#define rev(i,r,l) for(i=(r);i> (l);i--)
#define Each(i,v) for(i=v.begin();i!=v.end();i++)
#define r(x) read(x)
typedef long long ll ;
typedef double lf ;
int CH , NEG ;
template <typename TP>inline void read(TP& ret) {
ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;
if (CH == '-') NEG = true , CH = getchar() ;
while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
if (NEG) ret = -ret ;
}
#define kN 100010LL
struct node {
int val,id;
bool operator < (const node&b)const{ if (val==b.val) return id<b.id; return val<b.val; }
};
int N, M, K, Q, P;
int lef[kN], dow[kN], rig[kN], up[kN];
bool ok(int d) {
//std::set<node>su,sd,sl,sr;
std::deque<int>su,sd,sl,sr;
node tmp;
for(int i=1,tu,td,tl,tr;i<=N;i++) {
while (!su.empty()&&up[i]<=up[su.back()]) su.pop_back(); su.push_back(i);
while (!sr.empty()&&rig[i]<=rig[sr.back()]) sr.pop_back(); sr.push_back(i);
while (!sd.empty()&&dow[i]>=dow[sd.back()]) sd.pop_back(); sd.push_back(i);
while (!sl.empty()&&lef[i]>=lef[sl.back()]) sl.pop_back(); sl.push_back(i);
if (i<d) continue;
if (su.front()<=i-d) su.pop_front();
if (sd.front()<=i-d) sd.pop_front();
if (sl.front()<=i-d) sl.pop_front();
if (sr.front()<=i-d) sr.pop_front();
tu = up[su.front()];
tr = rig[sr.front()];
td = dow[sd.front()];
tl = lef[sl.front()];
if (tu-td+1>=d && tr-tl+1>=d) return true;
}
return false;
}
ll tot, ans, now, num;
int main() {
int i,L,R,mid,Max;
r(N), r(M), r(K), r(P), r(Q);
tot=0;
Rep (i,1,N) r(lef[i]), r(dow[i]), r(rig[i]), r(up[i]),tot+=(rig[i]-lef[i]+1LL)*(up[i]-dow[i]+1LL);
L = 1, R = N+1;
while (R-L > 1) { // [L,R)
mid = (L+R)/2;
if (ok(mid)) L=mid;
else R=mid;
}
ans = 0;
Max = L;
Rep (i,1,Max) {
num = tot+1LL-1LL*i*i*i;
now = 1LL*i*P+num*Q;
if (now>ans) ans = now;
}
printf("%lld\n", ans);
END: getchar(), getchar();
return 0;
}