Median (二分答案 + 二分查找)

Median

题意:

有N个整数,计算两两不同的整数间的差值,然后找到差值中的中位数.

思路:

二分答案 + 二分查找

题目数据范围是xi <= 1e9,N <= 1e5;如果直接暴力1e10的复杂度必爆;1e9数据需要longlong处理;

二分枚举中位数的可能值,然后二分查找满足条件的个数;

这里我们找的个数是比中位数小的数的个数,这个式子中一共有n * (n - 1) / 2个数 那么偶数个的中位数就是 n * (n - 1) / 4 ,奇数就是n * (n - 1) / 4 + 1;

直接给每个值加上中位数,然后upper_bound统计有多少个比中位数值小的数即可,最后看是否满足一半的个数即可

根据取大取小,合理使用lower_bound和注意往那一边进行搜索

AC代码:
取大的

#include <iostream>
#include <cstdio>
#include <algorithm>
 
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
int a[N];
ll n, m;

bool check(int x){
    ll sum = 0;
    for(int i = 0;i < n;i ++){
        int pos = n - (upper_bound(a,a + n,a[i] + x) - a);
        sum += pos;
    }
    return sum <= m;
}

int main(){
    while(~scanf("%d",&n)){
        for(int i = 0;i < n;i ++) scanf("%d",&a[i]);
        sort(a,a + n);
        m = n * (n - 1) / 4;
//        if(m & 1) m = m / 2;
//        else m = m / 2;
        int l = -1,r = a[n - 1] - a[0];
        while(l < r){
            int mid = (l + r) >> 1;
            if(check(mid)) r = mid;
            else l = mid + 1;
        }
        printf("%d\n",l);
    }
    return 0;
}

取小的

# include <iostream>
# include<cstdio>
# include <algorithm>
 
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
int a[N];
ll n, m;
 
bool check(int x){
    ll sum = 0;
    for(int i=0; i<n-1; ++i){ //统计有多少个比x小
        int pos = upper_bound(a+i, a+n, a[i]+x)-a;
        sum += pos - i - 1;
        if(sum >= m)
            return true;
    }
    return false;
}

int main(){
    while(~scanf("%lld",&n)){
        for(int i=0; i<n; ++i)
            scanf("%d",&a[i]);
        ll tmp = n*(n-1)>>1;
        if(tmp&1)
            m = (tmp>>1)+1;
        else
            m = tmp>>1;
        sort(a, a+n);
        int l=0, r=a[n-1]-a[0], mid;
        while(l<r)
        {
            int mid = (l + r)>>1;
            if(check(mid))
                r = mid;
            else
                l = mid+1;
        }
        printf("%d\n",r);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值