mathlover和她的粉丝团 西安电子科技大学第二届程序设计新生赛(同步赛)

链接: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大。
posted @ 2018-12-16 10:56  UUUUh  阅读(190)  评论(0编辑  收藏  举报