洛谷-P1923 【深基9.例4】求第 k 小的数

 

题目描述

输入 nn(n<5000000n<5000000 且 nn 为奇数) 个数字 a_i(0<a_i<10^9)ai​(0<ai​<109) ,输出这些数字的第 kk 小的数。最小的数是第 0 小。

输入格式

输出格式

输入输出样例

输入 #1复制

5 1
4 3 2 1 5

输出 #1复制

2

分析:

这题看起来很简单,但是必须搞明白一个问题,到底有没有重复的数字,例如1,2,2,3,5,第2小的数到底是重复的那个2,还是跳过重复的取3?这个纠结了很久,看了看大家的答案,似乎是第一种,就是不管重复,排序好之后直接输出a[k]就行(数组从0开始),那手撸快排,其他不多说,走你

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

int n;
int k;
int a[5000005];

void quicksort(int left,int right);
int main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	cin>>a[i];
	//quicksort(1,n);
	sort(a,a+n);
	//for(int i=1;i<=n;i++)
	//cout<<a[i]<<" ";
	//cout<<endl;
		/*
	int rank=-1;
	int lasti=-1;
	for(int i=1;i<=n;i++)
	{
		if(a[i]!=lasti)
		{
			rank++;
			if(rank==k)
			{
				cout<<a[i];
				break;
			}
		}
	}
	*/
	cout<<a[k];
	return 0;
}
void quicksort(int left,int right)
{
	int low=left;
	int high=right;
	int mid=a[(low+high)/2];
	do
	{
		while(a[low]<mid) low++;
		while(a[high]>mid) high--;
		if(low<=high)
		{
			swap(a[low],a[high]);
			low++;
			high--;
		}
	}while(low<=high);
	if(left<high) quicksort(left,high);
	if(low<right) quicksort(low,right);
}

三个对了,俩超时,想想也是,五百万的界限,稍微有点 不好就会超时吧,而且我还考虑到手写的快排或许没有sort效率高,专门换成了sort,但是还是超时,问题应该不是在这里,去看看题解吧

大家好厉害,原来STL还有nth_element这个函数,这个函数主要用来将数组元素中第k小的整数排出来并在数组中就位

用法:nth_element(数组名,数组名+第k小元素,数组名+元素个数)

话不多说,快排删了,来这个函数

#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;

int n;
int k;
long long int a[5000005];

void quicksort(int left,int right);
int main()
{
	cin>>n>>k;
	//scanf("%d",&n);
	//scanf("%d",&k);
	for(int i=0;i<n;i++)
    cin>>a[i];
	//scanf("%d",&a[i]);
	//cin>>a[i];
	nth_element(a,a+k,a+n);
	cout<<a[k];
	return 0;
}

走你,Σ( ° △ °|||)︴,还是超时了,这是为什么,就这不到几十行的代码,凭什么你AC我就超时,仔细对比了下和别人的代码,貌似唯一的不同点就在于我用的是cin,而他用的是scanf? 别开玩笑了,都什么时候了还在用C语言的scanf,cin不香吗?但也没什么其他好改的了,就先试试吧,改成scanf

#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;

int n;
int k;
long long int a[5000005];

void quicksort(int left,int right);
int main()
{
	cin>>n>>k;
	//scanf("%d",&n);
	//scanf("%d",&k);
	for(int i=0;i<n;i++)
	scanf("%d",&a[i]);
	//cin>>a[i];
	nth_element(a,a+k,a+n);
	cout<<a[k];
	return 0;
}

AC了?!!为什么,凭什么,难道我cin干不过scanf?我不信,我去查查

然而.....https://www.cnblogs.com/limera/p/5405705.html

还是我太年轻了,cin就是干不过scanf,这篇博客说的很清楚

scanf是格式化输入,printf是格式化输出。 
cin是输入流,cout是输出流。效率稍低,但书写简便。 
 
格式化输出效率比较高,但是写代码麻烦。 
 
流输出操作效率稍低,但书写简便。 
 
cout之所以效率低,正如一楼所说,是先把要输出的东西存入缓冲区,再输出,导致效率降低。 

就这样,scanf效率就是高,而且要注意,这道题最高可是要读取五百万个数字,一个数cin或许不会比scanf慢多少,但是再小的时间,乘以五百万,都是一个大时间,哎,以后要注意了...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章