[二分]基于第K大数的思考 (poj3579)

原问题1 - poj3579

下面给出第一种解法:

bool check(int mid){
ll cnt = 0,i = 0;
for(int i=0;i<n;i++) {
cnt += arr + n - lower_bound(arr+i+1,arr+n,arr[i] + mid);
}
return cnt >= (m/2+1);
}

/**
给你n个数，然后求它们两两相减的绝对值，然后找出这些绝对值的中位数。 解题思路
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
int arr[maxn],n;
ll m;
bool check(int mid){
ll cnt = 0,i = 0;
for(int i=0;i<n;i++) {
cnt += arr + n - lower_bound(arr+i+1,arr+n,arr[i] + mid);
}
return cnt >= m/2+1;
}
int main()
{
while(~scanf("%d",&n)) {
for(int i=0;i<n;i++) scanf("%d",&arr[i]);
m = n * (n-1) / 2;
sort(arr,arr+n);
int left = 0,right = arr[n-1] - arr[0];
while(left <= right) {
int mid = (left + right) / 2;
if(check(mid)) left = mid + 1;
else right = mid - 1;
}
printf("%d\n",right);
}
}

第二种解法

bool check(int mid){
ll cnt = 0,i = 0;
for(int i=0;i<n;i++) {
cnt += (upper_bound(arr+i,arr+n,arr[i] + mid) - 1 - arr- i);
}
return cnt >= m;
}

m = n * (n-1) / 2;
if(m & 1) m++;
m >>= 1;

/**
给你n个数，然后求它们两两相减的绝对值，然后找出这些绝对值的中位数。 解题思路
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
int arr[maxn],n;
ll m;
bool check(int mid){
ll cnt = 0,i = 0;
for(int i=0;i<n;i++) {
cnt += (upper_bound(arr+i,arr+n,arr[i] + mid) - 1 - arr- i);
}
return cnt < m;
}
int main()
{
while(~scanf("%d",&n)) {
for(int i=0;i<n;i++) scanf("%d",&arr[i]);
m = n * (n-1) / 2;
if(m & 1) m++;
m >>= 1;
sort(arr,arr+n);
int left = 0,right = arr[n-1] - arr[0];
while(left <= right) {
int mid = (left + right) / 2;
if(check(mid)) left = mid + 1;
else right = mid - 1;
}
printf("%d\n",left);
}
}