zoukankan      html  css  js  c++  java
  • 一维点距的中位数 (分治)

    题面

    $ solution: $

    这道题其实挺水的,主要是考当我们看到题目要求所有距离的中位数时,我们能否想到答案的单调性进而想到二分答案。(像我这种蒟蒻就想不到)

    首先中位数,它是很特殊的一个数,我们发现如果直接求它复杂度很高有(O(n^2)),但是如果我们是判断一个数是不是中位数就不一样了:只要我们排个序,就可以用贪心(O(n))的求出是否刚好有一半的点距小于它,如果小于它的点距没有一半就说明中位数大于当前这个数,如果小于它的点距超过一半就说明中位数小于当前这个数。

    而我们用贪心求小于当前数点距的数目时,因为排过序,直接尺取法即可(就是扫一遍)

    $ code: $

    #include<iostream>
    #include<cstdio>
    #include<iomanip>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<ctime>
    #include<cmath>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    
    #define ll long long
    #define db double
    #define inf 0x7fffffff
    #define rg register int
    
    using namespace std;
    
    int n,m,k,ans;
    int a[50005];
    
    inline int qr(){
    	char ch;
    	while((ch=getchar())<'0'||ch>'9');
    	int res=ch^48;
    	while((ch=getchar())>='0'&&ch<='9')
    		res=res*10+(ch^48);
    	return res;
    }
    
    inline bool check(ll x,int k){
    	int tot=0;
        for(rg i=1,j=2;i<=n;++i){
    		while(a[j]-a[i]<=x&&j<=n)++j;
    		tot+=j-i-1;
    	}
    	return tot<k?0:1;
    }
    
    inline int fen(int k){
    	ll l=1,r=inf,mid;
    	while(l<=r){
    		mid=(l+r)>>1;
    		if(check(mid,k))r=mid-1;
    		else l=mid+1;
    	}return l;
    }
    
    int main(){
    	freopen("game.in","r",stdin);
    	freopen("game.out","w",stdout);
    	n=qr(); m=(ll)n*(n-1)/2;
    	for(rg i=1;i<=n;++i)a[i]=qr();
    	sort(a+1,a+n+1);
    	ans=fen(m/2+1);
    	if(!(m&1))ans=((ll)ans+(ll)fen(m/2))/2;
    	printf("%d
    ",ans);
    	return 0;
    }
    
    
  • 相关阅读:
    Nim or not Nim? hdu3032 SG值打表找规律
    Maximum 贪心
    The Super Powers
    LCM Cardinality 暴力
    Longge's problem poj2480 欧拉函数,gcd
    GCD hdu2588
    Perfect Pth Powers poj1730
    6656 Watching the Kangaroo
    yield 小用
    wpf DropDownButton 源码
  • 原文地址:https://www.cnblogs.com/812-xiao-wen/p/10363209.html
Copyright © 2011-2022 走看看