题解 CF1355E Restorer Distance

[题目链接](Restorer Distance - 洛谷 | 计算机科学教育新生态 (luogu.com.cn))

发现,操作三(移动砖块)也可以转化为先拿一个砖块(操作二),再放一个砖块(操作一),那么当 MA+R 时,当然尽可能使用操作三,但是当 M>A+R 时,使用操作三还不如先用操作二再用操作一,所以先对 M 做处理:M=min{M,A+R},这样保证用操作三永远不劣。

如果知道最终所有砖块的高度,那么求解代价是简单的,通过猜测,发现函数是单谷函数(三分处理),最终结果确实如此,下面给出证明。

P 表示需要向上填补的砖块数,Q 表示需要向下削减的砖块数。A 表示向上填的代价,R 表示向下减的代价。n 表示砖块总数,H 表示最终砖块到达的高度,hi 表示所有砖块的初始高度,W 表示总代价。

我们发现,对应不同情况,总代价有以下两种情况(注:式子经过恒等变形,需要进行一步推导):

W={Q(MA)+PA,if PQP(MR)+QR,if PQ

容易发现,代价分成两端,不妨分开证明:

PQ

我们想要发现函数的增减性,不妨考虑相邻函数值的差值(即函数的增量)。

HH+1,记 P 的增加量 ΔP,记 Q 的减小量 ΔQ。注意:此时一定有 ΔP+ΔQ=n

那么 ΔP=(hiH)(由于原来在高度及以下,现在高度加一,显然会导致这些需要向上增的加一),同理 ΔQ=(hi>H)

那么原来贡献 W=Q(MA)+PA 变为 W=(QΔQ)(MA)+(P+ΔP)A,考虑 W 的增量,

ΔW=WW=ΔPAΔQ(MA)=AnMΔQ

不难发现,此处 ΔQ 是不增的(感性上直接理解为减即可),那么 ΔW 就是增的。

所以我们证明了,在 PQ 时,随着 H 增加函数值 W 增。

P<Q

同上可以证明,在这个区间内 W 减。


不妨思考一个问题:当 H 增加,PQ 分别怎么变化。

H 特别小的时候,P 肯定很小,Q 肯定很大,而当 H 慢慢增加,P 会逐渐变大,Q 会逐渐变小,最终在 P=Q 是时候发生转折,从 P<Q 的情况过渡为 PQ 的情况。

所以整个函数一定是先降后增,即单谷函数。

但三分还需要满足一个条件,即:非极值点处不能出现平台

出现平台则 ΔW=0

那么由于当 ΔW 是单调的(上文证明),例如对于 PQ 的情况来讲,ΔW 单调不降,也就是说,若 ΔW=0,只有可能在极值点处取。所以便证明了 平台只有可能在极值点处取

这样我们便证明了三分正确性。

总结:

  • 证明函数增减考虑相邻差值;
  • 对于分段函数证明,如果需要证明函数是单谷,则考虑证明两个分段函数增减性不同;
  • 对于多变量,考虑找出变量与常量关系。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+10;
int n,a,r,m;
int h[N];
LL calc(int H) {
LL s1=0,s2=0;
//s1需要往上加,s2需要往下减
for(int i=1;i<=n;i++) {
if(h[i]>H) s2+=h[i]-H;
if(h[i]<H) s1+=H-h[i];
}
if(s1>s2) return s2*m+(s1-s2)*a;
else return (s2-s1)*r+s1*m;
}
int main(){
cin>>n>>a>>r>>m;
m=min(m,a+r);
int l=0,r=0;
for(int i=1;i<=n;i++) {
cin>>h[i];
r=max(r,h[i]);
}
while(r-l>=3) {
int lmid=l+(r-l)/3,rmid=r-(r-l)/3;
if(calc(rmid)>calc(lmid)) r=rmid;
else l=lmid;
}
cout<<min({calc(l),calc(l+1),calc(l+2)});
return 0;
}
posted @   2017BeiJiang  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
点击右上角即可分享
微信分享提示