链接:https://ac.nowcoder.com/acm/contest/316/I
来源:牛客网
题解: 三分加暴力模拟,具体解释看代码注释,代码来自牛逼网友。
另附三分讲解博客:https://blog.csdn.net/littlewhite520/article/details/70144763
下面是官方给的题解,这里提供第一种
我们都知道 二分查找 适用于单调函数中逼近求解某点的值。
如果遇到凸性或凹形函数时,可以用三分查找求那个凸点或凹点。
代码:
#include <iostream>
#include <bits/stdc++.h>
#define mid ((l+r)/2)
using namespace std;
#define int long long
const int maxn=1e6+5;
int s[maxn];
int add[maxn],red[maxn];
int n;
void init(){
for(int i=1;i<=maxn;i++)
add[i]=add[i-1]+(i-1)/2;//增加一个人代价为当前人数的一半
for(int i=maxn;i>=1;i--)
red[i]=red[i+1]+ i+1;//减少一个人代价为当前人数
}
int f(int x){
int ans=0;
for(int i=1;i<=n;i++){
if(s[i]>x)
ans+=red[x]-red[s[i]]; // 累计减少的代价
else
ans+=add[x]-add[s[i]]; //累计增加的代价
}
return ans;
}
signed main(){
init();
while(cin>>n){
for(int i=1;i<=n;i++)
cin>>s[i];
int l=1,r=1e6;
//int mid=((l+((r-l)/2)));
while(l+2<=r){
int ll=mid;//宏定义mid #define mid ((l+r)/2)
int rr=(ll+r)>>1;
if(f(ll)<f(rr))
r=rr;
else
l=ll;
}
cout<<min(f(l),f(r))<<endl;
}
return 0;
}
题目描述
ls是mathlover所有粉丝团的总团长,已知一共有n个mathlover的粉丝团,但是由于地域的差异,导致粉丝团的人数有差异,对于第i个粉丝团有ai个粉丝。mathlover希望所有粉丝团的人数一样,这样就可以雨露均沾,不会偏袒任何粉丝。对于一个粉丝团,增加一个粉丝的代价是当前粉丝团人数除以2,而减少一个粉丝的代价是当前粉丝团人数。你能帮助ls完成这个任务计算出最少需要花费多少使得所有粉丝团人数一样吗?
输入描述:
多组输入:
第一行:输入一个n,表示粉丝团的个数(n≤100000)
接下来一行,n个数ai,表示每个粉丝团的人数(1≤ai≤1e6)
输出描述:
对于每一行,输出一个数,表示使所有粉丝团人数一样的最小代价
示例1
输入
4
2 3 4 5
输出
8
说明
关于样例:将4个粉丝团的人数都变为4,对于第一个团需要的代价为2/2+3/2=2,对于第二个团需要的代价为3/2,对于三个团需要的代价为0,对于第四个团需要的代价为5,2+1+5=8。而变成其他任何人数,代价都比8大。