• CF1355E Solution


    题目链接

    题解

    如果(M>A+R)的话(可能还要加上些奇奇怪怪的条件,总之就是全部弄成(M)最优的情况),把高度变为平均数一定最优,这样可以最大化使用(M)。如果(M)没有太大用处,而是要在(A,R)之间找平衡的话,可以发现最终高度一定为某个柱子的高度。简单证明:将(h)数组升序排序,设(h_i<res<h_{i+1})(res)为最终高度)。若(A>R),将(res)调至(h_i)可以使花费减少(icdot (res-h_i)cdot (A-R));若(A<R),将(res)调至(h_{i+1})可以使花费减少((n-i)cdot (h_{i+1}-res)cdot (R-A));若(A=R),则等于多少都无所谓。

    因此求出取平均数时的花费与取每个柱子时的花费就可以啦,时间复杂度(O(n))

    AC代码

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=1e5+10;
    int h[N],sum[N],n,a,r,m;
    int sol(int x,int op)
    {
    	int pos;
    	if(!op) pos=lower_bound(h+1,h+n+1,x)-h-1;//其实不需要二分
    	else pos=op;
    	int qwq=min(pos*x-sum[pos],sum[n]-sum[pos]-(n-pos)*x);
    	return qwq*m+(pos*x-sum[pos]-qwq)*a+(sum[n]-sum[pos]-(n-pos)*x-qwq)*r;
    }
    signed main()
    {
    	scanf("%lld%lld%lld%lld",&n,&a,&r,&m); m=min(a+r,m);
    	for(int i=1;i<=n;i++) scanf("%lld",&h[i]);
    	sort(h+1,h+n+1);
    	for(int i=1;i<=n;i++) sum[i]=sum[i-1]+h[i];
    	int ans=min(sol(sum[n]/n,0),sol(sum[n]/n+1,0));//平均数可能是小数,上下取整都试一下
    	for(int i=1;i<=n;i++) ans=min(ans,sol(h[i],i));
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    HEOI2017游记
    uoj228:基础数据结构练习题
    bzoj1494【Noi2007】生成树计数
    bzoj1975【Sdoi2010】魔法猪学院
    bzoj2957:楼房重建
    uoj169:元旦老人与数列
    bzoj2178:圆的面积并
    一道好题
    Codeforces Round #440(Div.2)
    Codeforces Round #439 (Div. 2)
  • 原文地址:https://www.cnblogs.com/violetholmes/p/14633750.html
Copyright © 2020-2023  润新知