由于 (1)(2)(3) 中除 P 以外都是定值,所以 f' 函数在 (1)(2)(3) 这三段分别单调不降。
(2)-(1) 得 M \Delta P+(X-Y+N)(A+R-M)。由于 \Delta P \ge 0,X-Y+N=X'+Y'+2(N-P)>0 且 M \le A+R,所以 (2)-(1) \ge 0,所以 (1)(2) 合起来也单调不降。
(3)-(2) 得 M \Delta P-(X-Y)(A+R-M)。由于 \Delta P \ge 0,X \le Y,M \le A+R,所以 (3)-(2) \ge 0,所以 (2)(3) 合起来也单调不降。
综上所述,f' 在定义域内单调不降—— f 是下凸函数。
P.S.
学过导数的人都知道 f' 就是 f 的导函数(注意 f 自变量为整数),而下凸函数的一种等价定义是其导函数单调不降,或表述为其二阶导函数恒 \ge 0。
如果你没学过导数,可以将其简单地理解为函数 f 变化量呈上升趋势,画个图就可以知道这可以判定下凸函数。
代码
P.S. 按本代码中整数三分的写法,边界条件应为 $[l,r]$ 的长度 $<3$,**若写法不同应具体情况具体处理**。
``` cpp
#include<bits/stdc++.h>
using namespace std;
int N,A,R,M;
const int max_N=1e5+5;
int h[max_N];
long long sum[max_N];
inline long long calc(int H)
{
int p=upper_bound(h+1,h+N+1,H)-h-1;
long long X=1ll*p*H-sum[p],Y=(sum[N]-sum[p])-1ll*(N-p)*H,c=min(X,Y);
return A*(X-c)+R*(Y-c)+M*c;
}
int main()
{
scanf("%d%d%d%d",&N,&A,&R,&M);
M=min(M,A+R);
for(int i=1;i<=N;++i)
scanf("%d",h+i);
sort(h+1,h+N+1);
for(int i=1;i<=N;++i)
sum[i]=sum[i-1]+h[i];
int l=h[1],r=h[N];
while(l<r)
{
int lmid=l+(r-l)/3,rmid=r-(r-l)/3;
if(calc(lmid)<calc(rmid))
r=rmid-1;
else
l=lmid+1;
}
printf("%lld\n",calc(l));
return 0;
}
```