ACdream1099 分治思想+快排优化+读入优化

news/2024/5/19 21:29:03 标签: 分治思想, 快速排序, C++STL

完整题目描述:

Problem Description

一天,萌萌的妹子--瑶瑶(tsyao)很无聊,就来找你玩。可是你们都不知道玩什么。。。尴尬了一阵子,机智的瑶瑶就提议:“这样吧,你说N个整数xi,然后在随意说一个数字k,我能够快速地说出这些数字里面第 大的数字。”

Input

第1行 两个整数N, K以空格隔开;

第2行 有N个整数(可出现相同数字,均为随机生成),同样以空格隔开。

0 < n ≤ 5*10^6 , 0 < k ≤ n

1 ≤ xi ≤ 10^8

Output

输出第  大的数字。

Sample Input

5 2
5 4 1 3 1

Sample Output

4

Hint

如2,2,1中三个数字中第一大数字为2,第二大数字也为2,第三大数字为1 。

一开始看到这道题的时候,我用的是快排,先排序然后直接输出“第K大”的那个数,很明显,这样做的话超时了,时间限制是2秒,而数据量高达500W(快排每秒排序的数据量大概在100W),所以我后来百思不得其解,在Acdream搜到这道题目之后就到百度看了下题解,发现这道题主要是对快排进行了优化。因为这道题是要找第K大的数字,很明显,如果我们对所有的数字进行排序的话,不必要的操作实在是太多了。所以我们这里要联想到快排排序的思想,快速排序每次排序一个数(即将“基准数”排序到升序或者降序后这个数在数组中所在的位置),所以,我们找第K大的数字的话,就只需要用降序快速排序算法,如果当前的“基准数”下标大于K-1的时候,那么我们只需要继续排序当前“基准数”左边的序列即可,反之则排序当前“基准数”右边的序列。当排序的“基准数”到第K-1个数的时候,然后程序马上终止,返回并输出这个数,这样的话节省了很多不必要的排序操作。核心代码:

if(k-1 == i)   return a[i];
else if (k - 1 < i)   quick_sort(left,i - 1,a);
else if (k - 1 > i)   quick_sort(i + 1,right,a);   //排序基准数左边和右边的序列

后来继续去看了这道题的题解,发现这道题除了快排优化之外,还可以继续优化,因为这道题的数据量非常大,所以,这道题可以在读入操作时进行“读入优化”。

读入优化操作:

int input()
{
    int ans=0;
    char a;
    while((a=getchar())<'0'||a>'9');
    ans=a-'0';
    while((a=getchar())>='0'&&a<='9')
    {
        ans=ans*10+a-'0';
    }
    return ans;
}

这样的话,在大量数据读入的时候会比scanf读入数据快的多一点,这个其实和scanf(“%d”,&n);  是等价的,但是实验证明这个是要更快一点的。
然后这道题还有另外的做法就是利用STL中内置的函数:

nth_element函数

使用方法:nth_element(start, start+n, end)

使第n大元素处于第n位置(从0开始,其位置是下标为n的元素),并且比这个元素小的元素都排在这个元素之前,比这个元素大的元素都排在这个元素之后,但不能保证他们是有序的。

注意这是升序排序下的结果,因此调用这个函数的时候核心代码为:
nth_element(num,num+n-k,num + n);
这样的话第K大元素正好就位于数组中倒数第几个位置。
附上这道题两种方法的源代码:
1.分治思想+快排优化+读入优化(其实读入优化也可以不用,大概快了200ms)
//降序快速排序,每次都以最左边的数字作为基准数
#include<cstdio>
#include<algorithm>
#include<vector>
#include<iostream>
using std::vector;
using std::cout;
int quick_sort(int left,int right,vector <int> &a);
int input();      //读入优化
int n,k;
int main()
{
    int ans;
    while(scanf("%d%d",&n,&k) == 2 && n && k)
    {
        vector <int> num(n);
        for(int i = 0;i < n;i++)
            num[i] = input();
        ans = quick_sort(0,n-1,num);
        printf("%d\n",ans);
    }
    return 0;
}

int input()
{
    int ans=0;
    char a;
    while((a=getchar())<'0'||a>'9');
        ans=a-'0';
    while((a=getchar())>='0'&&a<='9')
    {
        ans=ans*10+a-'0';
    }
    return ans;
}

int quick_sort(int left,int right,vector <int> &a)  //优化,减少排序次数
{
    int temp,i,j;               //用来存储基准数
    temp = a[left];         //每次都以最左边的数字作为基准数
    if(left > right)   return a[left-1];
    i = left;
    j = right;
    while(i < j)
    {
        while(i < j && a[j] <= temp)
            j--;
        while(i < j && a[i] >= temp)
            i++;
        if(i < j)
        {
            int flag = a[j];
            a[j] = a[i];
            a[i] = flag;
        }
    }
    a[left] = a[i];
    a[i] = temp;       //基准数归位
    if(k-1 == i)   return a[i];
    else if (k - 1 < i)   quick_sort(left,i - 1,a);
    else if (k - 1 > i)   quick_sort(i + 1,right,a);   //排序基准数左边和右边的序列
}
2.利用STL内置的nth_element函数
#include<cstdio>
#include<algorithm>
int num[5000005];
using std::nth_element;
int main()
{
    int n,k;
    while(scanf("%d%d",&n,&k) == 2 && n && k)
    {
        for(int i = 0;i < n;i++)
            scanf("%d",&num[i]);
        nth_element(num,num+n-k,num + n);
        printf("%d\n",num[n-k]);
    }
    return 0;
}


如有错误,还请指正,O(∩_∩)O谢谢


http://www.niftyadmin.cn/n/1038264.html

相关文章

Vue将HTML内容导出为 word文档 excel工作表 pdf文档等文件

最少我现在还实现不了通用的导出方法 只能将这三种文件的导出方式分别写出来 无论你想转那种都是需要FileSaver的 所以我们先导入第三方工具包 npm install xlsx file-saver --saveexcel的导出方式&#xff0c;就在需要导出的组件位置这样编写就好了&#xff0c;参考代码如下 …

关于codeforces比赛规则介绍(转载)

Codeforces 简称: cf(所以谈论cf的时候经常被误会成TX的那款游戏). 网址: codeforces.com   这是一个俄国的算法竞赛网站,由来自萨拉托夫州立大学、由Mike Mirzayanov领导的一个团队创立和维护,是一个举办比赛、做题和交流的平台.举办比赛和做题就不说了,“交流”指的是自带b…

Vue将HTML内容用打印机打印出来

首先导入第三方插件 npm install vue-print-nb --save在main.js中引入 import Print from vue-print-nb Vue.use(Print);接着就算打印的组件了 <template> <div id"printTest">打印区 </div> <button v-print"#printTest">打印…

CF578B 贪心+预处理优化+思维到位

题目描述&#xff1a; D. "Or" Gametime limit per test2 secondsmemory limit per test256 megabytesinputstandard inputoutputstandard outputYou are given n numbers a1, a2, ..., an. You can perform at most k operations. For each operation you can mu…

Vue引入Froala-Editor富文本编辑器

总是周知编辑器能让不懂变成语言的人也能写出一下html的基本标签&#xff0c;但坏处也非常明显&#xff0c;第一 编辑器所编辑出的内容是无法自适应的&#xff0c;第二 编辑器的内容无法调节响应式 但Froala却有一个不错的点&#xff0c;那就是他的图片可以设置百分比单位&…

常见的优化算法

优化一&#xff1a;预处理优化预处理优化之——前缀和优化&#xff1a;非常常见的优化方式。此处的前缀和指某数组的前i项和。如给定数组a[n]&#xff0c;求sum[n]。其中sum[i]a[0]a[1]...a[i]这里的sum[]数组即为数组a的前缀和数组。那么前缀和有什么用处呢&#xff1f;假设我…

Web自适应与响应式应用理解

页面适应所有屏幕大小我们自然是用更多的自适应 自适应的作用在于元素大小都是相对屏幕而言的 所以px显然是达不到这个概念的 自适应单位 1 VW vw是一个相对单位 一vw等于当前屏幕的 百分之一宽度 在只考虑宽度自适应是基本是主力 自适应单位 2 VH vh是一个相对单位 一vh等于当…

electron将vue项目变成电脑桌面应用

首先&#xff0c;我们在目录下建立一个vue项目 vue create electron在项目中导入electron vue add electron-builder之后你的项目就会发生一些改变 执行npm run electron:serve 试着运行一下 还有electro是需要依赖的 你可以检查一下系统中是否有生成electron和electron-buil…