选举学生会
题目描述
学校正在选举学生会成员,有 n ( n ≤ 999 ) n(n\le 999) n(n≤999) 名候选人,每名候选人编号分别从 1 到 n n n,现在收集到了 m ( m < = 2000000 ) m(m<=2000000) m(m<=2000000) 张选票,每张选票都写了一个候选人编号。现在想把这些堆积如山的选票按照投票数字从小到大排序。
输入格式
输入 n n n 和 m m m 以及 m m m 个选票上的数字。
输出格式
求出排序后的选票编号。
样例 #1
样例输入 #1
5 10
2 5 2 2 5 2 2 2 1 2
样例输出 #1
1 2 2 2 2 2 2 2 5 5
解体思路:就是简单的排序输出就行了,我们这儿不使用标准库的排序算法,自己手写随便两个排序
/*
* @Author: xiguan
* @Email: xiguan.teng@qq.com
* @Version: 1.0
* @Date: 2022-08-22 16:28:59
* @LastEditTime: 2022-09-26 18:57:54
*/
#include <bits/stdc++.h>
#include <stdlib.h>
using namespace std;
typedef long long ll;
ll n, m;
vector<ll> arr;
// O(n^2) 的算法有两个样例超时了,我们换个O(n*lg^n)的
void insertSort( vector<ll> &v ){
ll len = v.size();
if( len <= 1 ){
return ;
}
for( int idx = 1; idx < len; ++ idx ){
for( int jdx = idx - 1; jdx >= 0 && v[jdx] > v[jdx + 1]; -- jdx ){
swap( v[jdx], v[jdx + 1] );
}
}
}
pair<ll, ll> partition( vector<ll> &v, ll L, ll R ){
ll less_than = L - 1;
ll more_than = R;
while( L < more_than ){
if( v[L] < v[R] ){
swap( v[++ less_than], v[L ++] );
}else if( v[L] > v[R] ){
swap( v[-- more_than], v[L] );
}else{
L ++;
}
}
swap( v[more_than], v[R] );
return { less_than + 1, more_than };
}
void quickSort( vector<ll> & v, ll L, ll R ){
if( L < R ){
pair<ll, ll> t = partition( v, L, R );
quickSort( v, L, t.first - 1 );
quickSort( v, t.second + 1, R );
}
}
int main( int argc, char *argv[] ){
cin >> n >> m;
for( int idx = 0; idx < m; ++ idx ){
ll t; cin >> t;
arr.push_back( t );
}
quickSort( arr, 0, m - 1 );
for( int idx = 0; idx < m; ++ idx ){
cout << arr[idx] << ' ';
}
cout << endl;
return 0;
}
快速排序
题目描述
利用快速排序算法将读入的 N N N 个数从小到大排序后输出。
快速排序是信息学竞赛的必备算法之一。对于快速排序不是很了解的同学可以自行上网查询相关资料,掌握后独立完成。(C++ 选手请不要试图使用 STL
,虽然你可以使用 sort
一遍过,但是你并没有掌握快速排序算法的精髓。)
输入格式
第 1 1 1 行为一个正整数 N N N,第 2 2 2 行包含 N N N 个空格隔开的正整数 a i a_i ai,为你需要进行排序的数,数据保证了 A i A_i Ai 不超过 1 0 9 10^9 109。
输出格式
将给定的 N N N 个数从小到大输出,数之间空格隔开,行末换行且无空格。
样例 #1
样例输入 #1
5
4 2 4 5 1
样例输出 #1
1 2 4 4 5
解题思路:同样也是排序输出就行,我们上一次用了快排,这次用归并好了,O(n^2) 的算法很明显会超时,就不写了
/*
* @Author: xiguan
* @Email: xiguan.teng@qq.com
* @Version: 1.0
* @Date: 2022-08-22 16:28:59
* @LastEditTime: 2022-09-26 19:10:17
*/
#include <bits/stdc++.h>
#include <stdlib.h>
using namespace std;
typedef long long ll;
ll n;
vector<ll> arr;
void merge( vector<ll> &v, ll L, ll mid, ll R ){
ll *temp = new ll[R - L + 1];
ll i = 0;
ll p1 = L;
ll p2 = mid + 1;
while( p1 <= mid && p2 <= R ){
temp[i ++] = v[p1] < v[p2] ? v[p1 ++] : v[p2 ++];
}
while( p1 <= mid ){
temp[i ++] = v[p1 ++];
}
while( p2 <= R ){
temp[i ++] = v[p2 ++];
}
for( int idx = 0; idx < i; ++ idx ){
v[L + idx] = temp[idx];
}
delete[] temp;
}
void mergeSort( vector<ll> &v, ll L, ll R ){
if( L >= R || n <= 1){
return ;
}
ll mid = L + ((R - L) >> 1);
mergeSort( v, L, mid );
mergeSort( v, mid + 1, R );
merge( v, L, mid, R );
}
int main( int argc, char *argv[] ){
cin >> n;
for( int idx = 0; idx < n; ++ idx ){
ll t; cin >> t;
arr.push_back( t );
}
mergeSort( arr, 0, n - 1 );
for( int idx = 0; idx < n; ++ idx ){
cout << arr[idx] << " ";
}
puts( "" );
return 0;
}
求第 k 小的数
题目描述
输入 n n n( 1 ≤ n < 5000000 1 \le n < 5000000 1≤n<5000000 且 n n n 为奇数)个数字 a i a_i ai( 1 ≤ a i < 10 9 1 \le a_i < {10}^9 1≤ai<109),输出这些数字的第 k k k 小的数。最小的数是第 0 0 0 小。
请尽量不要使用 nth_element
来写本题,因为本题的重点在于练习分治算法。
输入格式
输出格式
样例 #1
样例输入 #1
5 1
4 3 2 1 5
样例输出 #1
2
解题思路:简单排序,返回数组相应下标即可。
解题的时候发现自己写的排序都会超时,这儿我们对快排优化一下,只找符合条件的那部分;
再次优化之后发现还是有tle问题,这时我们发现数据特别大,使用题目的提示吧
ps:突然想起之前刚学算法的时候,洛谷的题目很恶心,会卡 scanf 等等的时间,这道题 T 麻了。
/*
* @Author: xiguan
* @Email: xiguan.teng@qq.com
* @Version: 1.0
* @Date: 2022-08-22 16:28:59
* @LastEditTime: 2022-09-26 19:37:15
*/
#include <bits/stdc++.h>
#include <stdlib.h>
using namespace std;
typedef long long ll;
ll n, k;
ll arr[5000010];
void heapInsert( vector<ll> &v, ll index ){
while( v[index] > v[(index - 1) / 2] ){
swap( v[index], v[(index - 1) / 2] );
index = (index - 1) / 2;
}
}
void heapIfy( vector<ll> &v, ll index, ll heapsize ){
ll left_child = index * 2 + 1;
while( left_child < heapsize ){
ll largest = left_child + 1 < heapsize && v[left_child + 1] > v[left_child] ? left_child + 1 : left_child;
largest = v[largest] > v[index] ? largest : index;
if( largest == index ){
break;
}
swap( v[index], v[largest] );
index = largest;
left_child = index * 2 + 1;
}
}
void heapSort( vector<ll> &v, ll n ){
if( n <= 1 ){
return ;
}
for( int idx = 0; idx < n; ++ idx ){
heapInsert( v, idx );
}
ll heapsize = n;
swap( v[0], v[-- heapsize] );
while( heapsize > 0 ){
heapIfy( v, 0, heapsize );
swap( v[0], v[-- heapsize] );
}
}
void merge( vector<ll> &v, ll L, ll mid, ll R ){
ll *temp = new ll[R - L + 1];
ll i = 0;
ll p1 = L;
ll p2 = mid + 1;
while( p1 <= mid && p2 <= R ){
temp[i ++] = v[p1] < v[p2] ? v[p1 ++] : v[p2 ++];
}
while( p1 <= mid ){
temp[i ++] = v[p1 ++];
}
while( p2 <= R ){
temp[i ++] = v[p2 ++];
}
for( int idx = 0; idx < i; ++ idx ){
v[L + idx] = temp[idx];
}
delete[] temp;
}
void mergeSort( vector<ll> &v, ll L, ll R ){
if( L >= R || n <= 1){
return ;
}
ll mid = L + ((R - L) >> 1);
mergeSort( v, L, mid );
mergeSort( v, mid + 1, R );
merge( v, L, mid, R );
}
pair<ll, ll> partition( vector<ll> &v, ll L, ll R ){
ll less_than = L - 1;
ll more_than = R;
while( L < more_than ){
if( v[L] < v[R] ){
swap( v[++ less_than], v[L ++] );
}else if( v[L] > v[R] ){
swap( v[-- more_than], v[L] );
}else{
L ++;
}
}
swap( v[more_than], v[R] );
return { less_than + 1, more_than };
}
void quickSort( vector<ll> & v, ll L, ll R ){
if( L < R ){
pair<ll, ll> t = partition( v, L, R );
if( k < t.first ){
quickSort( v, L, t.first - 1 );
}else if( k > t.second ){
quickSort( v, t.second + 1, R );
}else{
cout << v[t.first] << endl;
exit( 0 );
}
}
}
int main( int argc, char *argv[] ){
cin >> n >> k;
for( int idx = 0; idx < n; ++ idx ){
scanf( "%d", &arr[idx] );
}
// quickSort( arr, 0, n - 1 );
nth_element( arr, arr + k, arr + n );
// for( int idx = 0; idx < n; ++ idx ){
// cout << arr[idx] << " ";
// }
// puts( "" );
cout << arr[k] << endl;
return 0;
}