10.26T1 二分

#3856 中位数

 

描述

给定n个数 a1,a2,...,an,求这n个数两两的差值(共n*(n-1)/2个)的中位数。

输入

第一行一个正整数n,表示数的个数。

接下来一行n个正整数,分别为a1,a2,...,an。

输出

输出仅一行一个数表示差值的中位数

样例输入[复制]
3
4 2 6
样例输出[复制]
2
提示

【样例解释】

  差值分别为 2,2,4,中位数为 2。

【数据规模和约定】

  对于30%的数据,n≤500。

  对于70%的数据,n≤5000。

  对于100%的数据,2≤n≤200000,2|ai。

 

 

 

 

二分中位数的大小,我们可以用一个单调队列线性查出对于一个数来说差小于这个值的数字个数,求和比较一下就可以了

当然也可以二分右端点,多了一个log

注意此题如果是偶数个差会导致中位数有概率是奇数,所以我们对此要二分两次,第一次二分位置强行在n/2的地方,第二次是n/2+1,两者加起来求值就可以了

我当然挂了25分啦

我写了一年错误的二分

code:

 1 #include<algorithm>
 2 #include<cmath>
 3 #include<ctime>
 4 #include<cstdio>
 5 #include<cstdlib>
 6 #include<cstring>
 7 #include<iostream>
 8 #include<queue>
 9 #include<vector>
10 using namespace std;
11 typedef long long ll;
12 const int N=200001;
13 ll n;
14 ll a[N];
15 ll smaller(ll mid)
16 {
17     ll L=1,R=1,ans=0;
18     for(;R<=n;R++)
19     {
20         while(a[R]-a[L]>mid) L++;
21         ans+=R-L;
22     }
23     return ans;
24 }
25 ll bsearch(ll pos)
26 {
27     ll L=0,R=a[n]-a[1];
28     while(L<=R)
29     {
30         ll mid=(L+R)>>1;
31         if(smaller(mid)<pos) L=mid+1;
32         else R=mid-1;
33     }
34     return L;
35 }
36 int main()
37 {
38     scanf("%lld",&n);
39     for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
40     sort(a+1,a+1+n);
41     ll num=(n-1)*n/2;
42     if(num%2) cout<<bsearch((num)/2);
43     else cout<<(bsearch(num/2)+bsearch(num/2+1))/2;
44     return 0;
45 }

over

 

转载于:https://www.cnblogs.com/saionjisekai/p/9858450.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值