• [洛谷] 求第 k 小的数 [ P1923 ]


    1.题目

    题目描述

    输入 n n n 1 ≤ n < 5000000 1 \le n < 5000000 1n<5000000 n n n 为奇数)个数字 a i a_i ai 1 ≤ a i < 10 9 1 \le a_i < {10}^9 1ai<109),输出这些数字的第 k k k 小的数。最小的数是第 0 0 0 小。

    请尽量不要使用 nth_element 来写本题,因为本题的重点在于练习分治算法。

    样例输入 #1

    5 1
    4 3 2 1 5
    
    • 1
    • 2

    样例输出 #1

    2
    
    • 1

    2.分析

    考察分治、排序~

    3.代码

    1.快读 + sort() 60pts

    由于数据读入量大,则考虑快读,但sort()为O(nlogn)算法,则会TLE

    #include 
    using namespace std;
    #include  //sort
    
    const int N = 5e6 + 10;
    int g[N];
    int n, k;
    inline int read()
    {
    	int x = 0, f = 1;
    	char ch = getchar();
    	while(!isdigit(ch))
    	{
    		if (ch == '-') f = -1;
    		ch = getchar();
    	}
    	while (isdigit(ch))
    	{
    		x = x * 10 + (ch ^ 48);
    		ch = getchar();
    	}
    	return x * f;
    }
    
    inline void write(int x)
    {
    	if (x < 0) putchar('-'), x = -x;
    	if (x > 9) write(x / 10);
    	putchar(x % 10 + '0');
    }
    
    int main()
    {
    	scanf("%d%d", &n, &k);
    	for (int i = 0; i < n; ++i) g[i] = read();
    	sort(g, g + n);
    	write(g[k]);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    在这里插入图片描述

    2.快排思想+分治 AC

    #include 
    using namespace std;
    //快排 + 分治
    const int N = 5e6 + 10;
    int g[N];
    int n, k;
    
    int q_s(int l, int r)
    {
    	//区间内只有一个数字,即为所求g[k]
    	if (l == r) return g[l];
    	
    	int i = l - 1, j = r + 1;
    	int x = g[l + r >> 1];   //分界值
    	while (i < j)
    	{
    		do i++; while (g[i] < x);
    		do j--; while (g[j] > x);
    		if (i < j) swap(g[i], g[j]);
    	}
    	
    	//如果k在 [l,j]区间,则返回前面的区间 ,否则返回 [j+1 , r]
    	if (k <= j) return q_s(l, j);
    	else return q_s(j + 1, r);
    }
    int main()
    {
    	scanf("%d%d", &n, &k);
    	for (int i = 0; i < n; ++i)
    		scanf("%d", &g[i]);
    	int res = q_s(0, n - 1);
    	printf("%d", res);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    在这里插入图片描述

    3.STL nth_element AC

    nth_element()详解

    //nth_element
    #include 
    using namespace std;
    #include 
    const int N = 5e6 + 10;
    int g[N];
    int n, k;
    int main()
    {
    	scanf("%d%d", &n, &k);
    	for (int i = 0; i < n; ++i)
    		scanf("%d", &g[i]);
    	nth_element(g, g + k, g + n);
    	printf("%d", g[k]);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这里插入图片描述

    4.总结

    分治思想 、 快排思想 ~

    5.更新日志

    2022.8.26 整理

    欢迎交流、讨论、指正~
    不正确、不理解之处欢迎评论留言~

  • 相关阅读:
    Docker进阶知识(深入浅出理解Docker)
    git笔记
    MATLAB常用命令大全,非常详细(持续更新中)
    vue页面菜单权限问题解决
    计算机毕业设计Java小说网站(系统+源码+mysql数据库+lw文档)
    ComfyUI搭建
    vector容器 常用函数
    web:[护网杯 2018]easy_tornado
    【OpenCV】-霍夫变换
    [cpu出错心得]
  • 原文地址:https://blog.csdn.net/qq_60404548/article/details/126548598