Median [二分]

来源:互联网 发布:ubuntu u盘挂载 编辑:程序博客网 时间:2024/06/05 04:51

题意:对于给定的n个数字数列,求|xixj|,i<j的结果构成的序列中的中位数是多少。
思路:首先计算中位数前应该有多少个数字,二分新序列的值,看满足小于等于他的差值有多少个。
二分的单调性:把新序列看做一个有序序列,本身具有单调性,二分上面的值。
二分的check(mid):对于当前差值x,枚举第一个数字找到第一个比它大的值,就可以统计一共有多少个差值小于等于x,看x与需要的个数的关系,就可以返回check值更新二分端点。

复杂度O(nlognlogn),cin关闭同步TLE了。

#include<iostream>#include<string>#include<cstdio>#include<cstring>#include<bitset>#include<algorithm>#include<map>#include<set>#include<queue>#include<vector>#include<cstdlib>#include<list>#include<stack>#include<cmath>#include<iomanip>using namespace std;//#pragma comment(linker, "/STACK:1024000000,1024000000")typedef long long LL;void debug() {cout << "ok running!" << endl;}int n, m;int a[100005];bool check(int x){    int cnt = 0;    for(int i=0; i<n; i++){        cnt += (upper_bound(a+i, a+n, a[i]+x)-1 - (a+i));    }    if(cnt >= m) return 1;    else return 0;}int main(){    //ios::sync_with_stdio(false);    #ifndef ONLINE_JUDGE    freopen("input.txt", "r", stdin);    #endif // ONLINE_JUDGE    while(~scanf("%d", &n))    {        int temp = n*(n-1)/2;        if(temp%2 == 0) m = c/2;        else m = temp/2 + 1;        for(int i=0; i<n; i++)           scanf("%d", &a[i]);        sort(a, a+n);        int l = -1, r = a[n-1] - a[0];        int ans = -1;        while(l <= r)        {            int mid = (l+r)>>1;            if(check(mid))            {                r = mid -1;                ans = mid;            }            else l = mid + 1;        }        printf("%d\n", ans);    }    return 0;}
原创粉丝点击