POJ - 3579 Median 二分

题目大意:给出n个数,要求将这n个数两两相减,把这些相减得到的数排序后,输出位置在中间的那个数

解题思路:如果两两相减再排序复杂度太高,肯定超时了,不妨换另一种思路

枚举最中间的那个数,然后判断一下相减得到的数有多少个大于等于枚举的数

如何判断上面所说的那句呢,其实不用把每个数相减,只需要排序一下,然后将当前这个数 + 枚举的那个数,然后在数组中找到大于等于这个数的第一个位置(lower_bound()),再用n减去那个数的位置就可以知道有多少个相减的结果会大于等于这个数了

最后只需要判断一下大于等于这个枚举数的数有几个就可以了,当这个数大于等于(n * (n - 1) / 2 / 2 - 1)就表示这个枚举数是小于或者等于这个最中间值的(等于的情况就是最中间值能有多个数相减得到)

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
#define maxn 100010
#define INF 0x3f3f3f3f
int n;
ll Max, num[maxn];
int low_bound(int l, int r, ll Num) {
    int L = l, R = r;
    while(L <= R) {
        int mid = (L + R) / 2;
        if(num[mid] < Num)
            L = mid + 1;
        else
            R = mid - 1;
    }
    return L;
}
bool judge(ll mid) {
    ll cnt = 0;
    for(int i = 0; i < n; i++)  {
        //cnt += (num + n) - lower_bound(num + i, num + n, num[i] + mid);
        cnt += n - low_bound(i,n-1,num[i] + mid);
    }
    ll m = (ll)n * (n - 1) / 2;
    return cnt >= (m / 2 + 1);
} 

ll solve() {
    ll l = 0, r = Max;
    while(l <= r) {
        ll mid = (l + r) / 2;
        if(judge(mid))
            l = mid + 1;
        else
            r = mid - 1;
    }
    return l - 1;
}

int main(){
    while(scanf("%d", &n) != EOF) {
        Max = -INF;
        for(int i = 0; i < n; i++) {
            scanf("%lld", &num[i]);
            Max = max(num[i], Max);
        }
        sort(num, num + n);
        printf("%lld\n", solve());
    }
    return 0;
}
时间: 2024-10-15 04:02:15

POJ - 3579 Median 二分的相关文章

POJ 3579 Median 二分+思维

POJ 3579 Median 二分+思维 题意 给你一些数,然后求这些数相互之间差的绝对值,然后绝对值排序,找到中间那个数. 解题思路 我反正一直开始是没有想到这个题竟然可以用二分来做.━━( ̄ー ̄*|||━━. 二分枚举答案,假设枚举值为mid,然后就是在排好序的序列中对每一个num[i]找到在i之后,有多少个大于num[i]+mid的数的个数(数列里的值比num[i]+mid大,说明该值与num[i]作差形成的新数列里的数比中位数mid大),用lower_bound计算所有差值比mid大于

poj 3579 Median 二分查找与lower_bound

题意: 给n个数,他们两两之间较大数减去较小数总共有n*(n-1)/2个数,要求这些数的中位数. 分析: 两次二分,第一次枚举答案,第二次判断该数是否可能成为中位数. 代码: //poj 3579 //sep9 #include <iostream> #include <algorithm> using namespace std; const int maxN=1e5+10; int a[maxN]; int n,m; int test(int x) { int sum=0; f

POJ 3579 Median(二分答案+Two pointers)

[题目链接] http://poj.org/problem?id=3579 [题目大意] 给出一个数列,求两两差值绝对值的中位数. [题解] 因为如果直接计算中位数的话,数量过于庞大,难以有效计算, 所以考虑二分答案,对于假定的数据,判断是否能成为中位数 此外还要使得答案尽可能小,因为最小的满足是中位数的答案,才会是原差值数列中出现过的数 对于判定是不是差值的中位数的过程,我们用尺取法实现. 对于差值类的题目,还应注意考虑边界,即数列只有一位数的情况. [代码] #include <cstdio

poj 3579 Median (二分搜索之查找第k大的值)

Description Given N numbers, X1, X2, ... , XN, let us calculate the difference of every pair of numbers: ∣Xi - Xj∣ (1 ≤ i < j ≤ N). We can get C(N,2) differences through this work, and now your task is to find the median of the differences as quickly

POJ 3579 3685(二分-查找第k大的值)

POJ 3579 题意 双重二分搜索:对列数X计算∣Xi – Xj∣组成新数列的中位数 思路 对X排序后,与X_i的差大于mid(也就是某个数大于X_i + mid)的那些数的个数如果小于N / 2的话,说明mid太大了.以此为条件进行第一重二分搜索,第二重二分搜索是对X的搜索,直接用lower_bound实现. #include <iostream> #include <algorithm> #include <cstdio> #include <cmath&g

POJ3579 Median —— 二分

题目链接:http://poj.org/problem?id=3579 Median Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8286   Accepted: 2892 Description Given N numbers, X1, X2, ... , XN, let us calculate the difference of every pair of numbers: ∣Xi - Xj∣ (1 ≤ i < 

poj 1975 Median Weight Bead(传递闭包 Floyd)

链接:poj 1975 题意:n个珠子,给定它们之间的重量关系,按重量排序,求确定肯定不排在中间的珠子的个数 分析:因为n为奇数,中间为(n+1)/2,对于某个珠子,若有至少有(n+1)/2个珠子比它重或轻,则它肯定不排在中间 可以将能不能确定的权值初始化为0,能确定重量关系的权值设为1 #include<stdio.h> #include<string.h> int a[110][110]; int main() { int T,n,m,i,j,k,d,x,sum; scanf(

POJ 3484 Showstopper 二分

 Showstopper Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1218   Accepted: 356 Description Data-mining huge data sets can be a painful and long lasting process if we are not aware of tiny patterns existing within those data sets. On

poj 1469 COURSES (二分匹配)

COURSES Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16877   Accepted: 6627 Description Consider a group of N students and P courses. Each student visits zero, one or more than one courses. Your task is to determine whether it is poss