week4 作业C TT的神秘礼物

TT 的神秘礼物

题目:
TT 是一位重度爱猫人士,每日沉溺于 B 站上的猫咪频道。
有一天,TT 的好友 ZJM 决定交给 TT 一个难题,如果 TT 能够解决这个难题,ZJM 就会买一只可爱猫咪送给 TT。
任务内容是,给定一个 N 个数的数组 cat[i],并用这个数组生成一个新数组 ans[i]。新数组定义为对于任意的 i, j 且 i != j,均有 ans[] = abs(cat[i] - cat[j]),1 <= i < j <= N。试求出这个新数组的中位数,中位数即为排序之后 (len+1)/2 位置对应的数字,’/’ 为下取整。
TT 非常想得到那只可爱的猫咪,你能帮帮他吗?

Input:

多组输入,每次输入一个 N,表示有 N 个数,之后输入一个长度为 N 的序列 cat, cat[i] <= 1e9 , 3 <= n <= 1e5

Output:

输出新数组 ans 的中位数

Example:

Input:
4
1 3 2 4
3
1 10 2
Output:
1
8

我的思路:
根据题意,我们要对于一个数组中,两个数的差的绝对值,然后计算绝对值数列的中位数。可以通过将数组从小到大排序,然后计算 后面的数-前面的数 ,这样可以去除绝对值。然后可以通过二分法进行优化。选取最大差值(即排序后数组的最后一个数减去第一个数)最为max,0为min,进行二分,计算mid的排名。因为,我们可以知道最后中位数的排名,所以只要对比排名就可以了。计算排名也可以用到二分法,即计算小于这个数的差值的个数(即计算差值比其小的数对对数就可以了)。
我的总结:
为了时间复杂度考虑,要尽量使用scanf,printf。(cin,cout一直超时,换成scanf,printf直接AC)

我的代码:

#include<cstdio>
#include<algorithm>
using namespace std;

long long cat[100000],N;

/*int count_rank(int P)
{
	int rank=0;
	for(int i=0;i<N;i++)
		{
			int l=i+1,r=N-1,ans=i,mid;
			while(l<=r)
			{
				mid=(l+r)>>1;
				if(cat[mid]-cat[i]<P) ans=mid,l=mid+1;
				else r=mid-1;
			}
			rank=rank+(ans-i);
		}
	return rank;
}*/

int count_rank(int P)
{
	int rank=0;
	for (int i=0;i<N;i++)
	{
		int l=i+1,r=N-1,ans=i;
		for(int q=0;q<15;q++)
		{
			int mid=(l+r)>>1;
		if(cat[mid]-cat[i]<=P)
		{
			ans=mid;
			l=mid+1;
		}
			else r=mid-1;
		 }
		rank+=ans-i;
	}
	return rank;
}

long long bifind()
{
	long long l=0 , r=cat[N-1]-cat[0],mid_rank=N*(N-1)/4+N*(N-1)/2%2,mid,ans;
	for(int i=0;i<20;i++)
	{	mid=(l+r)>>1;
		//cout<<count_rank(mid)<<endl;
		if(count_rank(mid)>=mid_rank)  {
		r=mid;
		}
		else l=mid;
	}
	return r;
}

int main()
{
    while(~scanf("%d",&N))
    {
    	for (int i=0;i<N;i++)
    	{
    		scanf("%lld",&cat[i]); 
		}
		sort(cat,cat+N);
		printf("%lld\n",bifind());
	}
	return 0;
}
发布了26 篇原创文章 · 获赞 0 · 访问量 446

猜你喜欢

转载自blog.csdn.net/qq_43738677/article/details/104886864