zoukankan      html  css  js  c++  java
  • 牛客挑战赛43 C-最优公式 二分,切比雪夫距离转曼哈顿距离

    最优公式

    题意

    有一个长为 (n) 的数组 (A1,A2,…,An)
    你需要找到两个实数 (a), (b),使得 (sum_{i=1}^n sum_{j=1}^n max (|A_i - a|, |A_j - b|)) 尽可能小。
    求出这个最小值。
    容易发现答案乘上 2 一定是整数,求出答案乘上 2 模 (10^9+7) 的值。

    分析

    将一个点((x,y))的坐标变为((x+y,x-y))后,原坐标系中的曼哈顿距离 = 新坐标系中的切比雪夫距离

    将一个点((x,y))的坐标变为((frac{x+y}{2},frac{x-y}{2}))后,原坐标系中的切比雪夫距离 = 新坐标系中的曼哈顿距离

    将题意转化为(n^2)个点((A_i,A_j)),找到一个点((a,b)),使得这(n^2)个点和((a,b))的切比雪夫距离之和最小,将((A_i,A_j))转为((A_i+A_j,A_i-A_j)),因为答案要乘二,所以这样转化之后,求切比雪夫距离就变成了求曼哈顿距离。

    因为所求的是曼哈顿距离,所以可以两个维度分别单独考虑,对于第一维(A_i+A_j),容易想到这(n^2)个点中从小到大第 (lfloor frac{n^2}{2} floor+1)个点到其他点的距离之和最小,可以二分这个点的大小(x),然后对每个(A_i)二分找到有多少个数(A_j)使得(A_i+A_j<x),找出第 (lfloor frac{n^2}{2} floor+1)个点后,同样可以这样对每个点二分计算贡献来计算答案,对第二维再做一遍类似的过程就可以了。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    #define rep(i,a,n) for (int i=a;i<=n;++i)
    #define per(i,n,a) for (int i=n;i>=a;--i)
    #define sz(x) ((int)(x).size())
    #define fi first
    #define se second
    #define pb push_back
    #define mp make_pair
    #define lson l,mid,p<<1
    #define rson mid+1,r,p<<1|1
    typedef pair<int,int> pii;
    #define ll long long
    const int inf=1e9;
    const int mod=1e9+7;
    const int N=1e5+10;
    int n;
    int a[N];
    ll b[N];
    bool ck(int x){
    	ll cnt=0;
    	rep(i,1,n) if(a[i]<=x){
    		int pos = lower_bound(a+1,a+n+1,x-a[i])-a-1;
    		cnt+=pos;
    	}
    	return cnt<=1ll*n*n/2;
    }
    bool ck1(int x){
    	ll cnt=0;
    	rep(i,1,n) {
    		int pos = upper_bound(a+1,a+n+1,a[i]-x)-a;
    		cnt+=n+1-pos;
    	}
    	return cnt<=1ll*n*n/2;
    }
    int main(){
    	ios::sync_with_stdio(false);
    	//freopen("in","r",stdin);
    	cin>>n;
    	rep(i,1,n) cin>>a[i];
    	sort(a+1,a+n+1);
    	rep(i,1,n) b[i]=(b[i-1]+a[i])%mod;
    	int l=1,r=1e9;
    	while(l<=r){
    		int mid=l+r>>1;
    		if(ck(mid)) l=mid+1;
    		else r=mid-1;
    	}
    	ll ans=0;
    	rep(i,1,n){
    		if(a[i]<=r){
    			int pos=upper_bound(a+1,a+n+1,r-a[i])-a-1;
    			ans=(ans-b[pos])%mod;
    			ans=(ans-1ll*pos*a[i]%mod)%mod;
    			ans=(ans+1ll*r*pos%mod)%mod;
    			int cpos=n-pos;
    			ans=(ans+1ll*a[i]*cpos%mod+b[n]-b[pos]-1ll*r*cpos%mod)%mod;
    		}else{
    			ans=(ans+b[n]+1ll*n*a[i]%mod-1ll*r*n%mod)%mod;
    		}
    	}
    	l=-1e9,r=1e9;
    	while(l<=r){
    		int mid=l+r>>1;
    		if(ck1(mid)) l=mid+1;
    		else r=mid-1;
    	}
    	rep(i,1,n){
    		int pos=lower_bound(a+1,a+n+1,a[i]-r)-a;
    		int cpos=n+1-pos;
    		ans=(ans+1ll*cpos*r%mod-1ll*a[i]*cpos%mod+b[n]-b[pos-1])%mod;
    		if(pos>0) ans=(ans-1ll*(pos-1)*r%mod+1ll*a[i]*(pos-1)%mod-b[pos-1])%mod;
    	}
    	ans=(ans%mod+mod)%mod;
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    Understanding CMS GC Logs--转载
    Understanding G1 GC Logs--转载
    gcview使用
    kafka源码分析之一server启动分析
    电商网站的初期技术选型--转
    An In-Depth Look at the HBase Architecture--转载
    Maven报错Missing artifact jdk.tools:jdk.tools:jar:1.7--转
    定时任务调度系统设计
    spark源码解析之scala基本语法
    Searching with regular sentences will only get you so far – if you need to find something a bit tricky turn to these advanced yet simple methods--转
  • 原文地址:https://www.cnblogs.com/xyq0220/p/13713630.html
Copyright © 2011-2022 走看看