Codeforces Round #643 (Div. 2) E(三分)

题目
题意: 给定长度为n的数组。有三种操作,求最小的花费使得数组中所有元素相同。
花费a,使得某个数++;
花费b,使得某个数–;
花费c,使得某个数+1,另一个数-1.
思路: 三分,函数值可以花O(n)的时间枚举得到,当然也可以维护前缀和二分求得。
那么为什么可以用三分呢,首先直接二分不太行,因为不具有单调性。
然后三分的使用条件就是具有极值点,假设最优解为所有数等于ans,那么ans不管是+1还是-1都会使答案变得更差或者不变(操作的消耗可能为0),所以可以三分找。
代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
//#define int long long
int a[N];
int n,m,k,T;
ll t1,t2,t3;
ll f(int x)
{
	ll sum = 0;
	ll sum1 = 0,sum2 = 0;
	for(int i=1;i<=n;++i)
	{
		if(a[i]<x) sum1 += (x-a[i]); //小于 
		else sum2 += (a[i]-x); //大于 
	}
	if(t3<t1+t2)
	{
		sum = 1ll*t3*min(sum1,sum2)+max(0ll,sum2-sum1)*t2+max(0ll,sum1-sum2)*t1;
	}
	else 
	{
		sum = sum2*t2+sum1*t1;
	}
	return sum;
}
ll find(int l,int r)
{
	int m1,m2; ll f1,f2;
	while(l<r)
	{
		m1 = l+(r-l)/3;
		m2 = r-(r-l)/3;
		f1 = f(m1);
		f2 = f(m2);
		if(f1>f2) l = m1+1;
		else r = m2-1;
	}
//	cout<<f(5)<<"??\n";
	return min(f1,f2);
}
void solve()
{
	cin>>n>>t1>>t2>>t3;
//	ll mx = 0;
	for(int i=1;i<=n;++i) cin>>a[i];
	ll ans = find(0,1000000000);
	cout<<ans;
}
signed main(void)
{
	solve();
	return 0;	
} 
/*
10 7122 8827 3205
452685204 144160553 743427456 403576146 888744473 313727757 22025193 886601085 576370788 787974081
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值