二分答案-新定义数组的中位数(题解)

题意:给定一个 N 个数的数组 cat[i],并用这个数组生成一个新数组 ans[i]。新数组定义为对于任意的 i, j 且 i != j,均有 ans[] = abs(cat[i] - cat[j]),1 <= i < j <= N。试求出这个新数组的中位数,中位数即为排序之后 (len+1)/2 位置对应的数字,’/’ 为下取整。cat[i] <= 1e9 , 3 <= n <= 1e5
思路:因为如果求出新数组进行排序找中位数,复杂度为o(n^2),显然在1s内不能运行。所以这时可以运用二分答案,对答案进行二分,对于每个答案,都求出一个名次(<=该数的个数),名次大于等于(len+1)/2的fist即是中位数
总结:单调的都可以进行二分!重要的是可以看出中位数对应的名次,这是单调的,所以想到二分答案!
反思:卡常,scanf比cin输入的时间快
代码

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std; 
int a[100002];
int main()
{
	int n;
	while(scanf("%d",&n)!=EOF)
	{   for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);//注意:scanf比cin快!!!
		sort(a+1,a+n+1);
		int kk=(n*(n-1)/2+1)/2;
		int l=0;int r=1000000000;int flag=-1;
		while(l<=r)//二分中位数 
		{   
			int mid=(l+r)/2;int count=0;
			for(int i=1;i<=n;i++) 
			{    
				  int num=mid+a[i];
				  int ll=i+1;int rr=n;int pos=-1;
				  while(ll<=rr)
				  {
				  	int mmid=(ll+rr)/2;
				  	if(a[mmid]<=num)
				  	{ 
				  		pos=mmid;ll=mmid+1; 
				  		
					  }else rr=mmid-1;
				  }
				  if(pos!=-1) count=count+pos-(i+1)+1;
     	}
			if(count>=kk) //找到名次>=(len+1)/2   不要只找等于  因为可能会有重复的值,都等于中位数,这时,名次会高 
		    	{        //找第一个first即可 
				flag=mid;r=mid-1;
		    	}
		    	else  l=mid+1;
		    		
		}  cout<<flag<<endl;
	}  return 0;
} 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值