正题
题目链接:https://ac.nowcoder.com/acm/contest/7413/C
题目大意
给一个序列AAA,求两个a,ba,ba,b使得∑i=1n∑j=1nmax{∣Ai−a∣,∣Aj−b∣}\sum_{i=1}^n\sum_{j=1}^nmax\{|A_i-a|,|A_j-b|\}i=1∑nj=1∑nmax{∣Ai−a∣,∣Aj−b∣}最小。
解题思路
因为是取maxmaxmax,也就是a,ba,ba,b中最劣的那一个,所以显然有a=ba=ba=b。
考虑如和求aaa,不难发现其实答案就是对于每个Ai+Aj2\frac{A_i+A_j}{2}2Ai+Aj的中位数。我们可以二分答案,然后求在midmidmid前有多少个Ai+AjA_i+A_jAi+Aj,这个显然也可以将数组排序后二分求得(其实不二分用指针也行)。
时间复杂度O(nlog2n)O(n\log^2 n)O(nlog2n)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll XJQ=1e9+7;
ll n,a[110000];
ll find(ll x){ll l=1,r=n;while(l<=r){ll mid=(l+r)>>1;if(a[mid]<=x)l=mid+1;else r=mid-1;}return r;
}
ll check(ll mid){ll ans=0;for(ll i=1;i<=n;i++)ans+=find(mid-a[i]);return ans;
}
int main()
{scanf("%lld",&n);for(ll i=1;i<=n;i++)scanf("%lld",&a[i]);sort(a+1,a+1+n);ll l=1,r=1e9,k=n*n;while(l<=r){ll mid=(l+r)>>1;if(check(mid)>=(k+1)/2)r=mid-1;else l=mid+1;}ll ans=0;for(ll i=1;i<=n;i++)a[i]=abs(a[i]*2-l);sort(a+1,a+1+n);for(ll i=1;i<=n;i++)ans+=a[i]*((i-1)*2+1);printf("%lld",ans%XJQ);
}