排序专项练习
在比赛中排序题一般不会直接出,大部分会和其他考点一起出题,比较常见的形式是贪心算法
A
这个题有比较多的解法
解一
- 先排序后去除偶数
#include <algorithm>#include <cstdio>const int MAXN = 5e2 + 1;int n;int ar[MAXN];int main(void) {scanf("%d", &n);for (int i = 1; i <= n; i++) {scanf("%d", &ar[i]);}std::sort(ar + 1, ar + 1 + n);int flag = 0;for (int i = 1; i <= n; i++) {if (ar[i] % 2) {if (flag) {putchar(',');} else {flag = 1;}printf("%d", ar[i]);}}return 0;}
B
#include <algorithm>#include <iostream>#include <string>using namespace std;const int MAXN = 1e2 + 1;int n, k;struct Node {string name;int time;} ar[MAXN];int cmp(Node a, Node b) { return a.time < b.time; }int main(void) {cin >> n >> k;for (int i = 1; i <= n; i++) {cin >> ar[i].name >> ar[i].time;}sort(ar + 1, ar + 1 + n, cmp);cout << ar[k].name << endl;return 0;}
#include <algorithm>#include <iostream>#include <string>using namespace std;const int MAXN = 1e2 + 1;int n, k;struct Node {string name;int time;int operator<(Node a) const { return this->time < a.time; }} ar[MAXN];int cmp(Node a, Node b) { return a.time < b.time; }int main(void) {cin >> n >> k;for (int i = 1; i <= n; i++) {cin >> ar[i].name >> ar[i].time;}sort(ar + 1, ar + 1 + n);cout << ar[k].name << endl;return 0;}
C
- 冒泡排序,模拟这个过程
#include <cstdio>int n;int data[100001];int ans;int main(void) {scanf("%d", &n);for (int i = 1; i <= n; i++) scanf("%d", &data[i]);for (int i = 1; i <= n; i++) {for (int j = 1; j <= n - 1; j++)if (data[j] > data[j + 1]) {ans++;int temp = data[j];data[j] = data[j + 1];data[j + 1] = temp;}}printf("%d", ans);return 0;}
D
- 桶排序
#include <cstdio>const int MAXN = 1e3 + 1;int n;int ar[MAXN];int main(void) {scanf("%d", &n);for (int i = 1; i <= n; i++) {int temp;scanf("%d", &temp);ar[temp]++;}int maxn = 1;for (int i = 2; i < MAXN; i++) {if (ar[maxn] < ar[i]) {maxn = i;}}printf("%d", maxn);return 0;}
E
- 和上一题类似,一道非常经典的题
#include <cstdio>const int MAXN = 1e3 + 1;int n;int ar[MAXN];int main(void) {scanf("%d", &n);int m = n;for (int i = 1; i <= n; i++) {int temp;scanf("%d", &temp);if (!ar[temp]) {ar[temp]++;} else {m--;}}printf("%d\n", m);for (int i = 1; i < MAXN; i++) {if (ar[i]) {printf("%d ", i);}}return 0;}
F
#include <algorithm>#include <cstdio>#include <iostream>#include <string>using namespace std;const int MAXN = 41;int n;int b, g;double boy[MAXN];double girl[MAXN];int main(void) {cin >> n;for (int i = 1; i <= n; i++) {string sex;double temp;cin >> sex >> temp;if (sex == "male") {boy[++b] = temp;} else {girl[++g] = temp;}}sort(boy + 1, boy + b + 1);sort(girl + 1, girl + 1 + g, greater<double>()); // 第三个参数使数据降序排列for (int i = 1; i <= b; i++) {printf("%.2lf ", boy[i]);}for (int i = 1; i <= g; i++) {printf("%.2lf ", girl[i]);}return 0;}
G
- 可以使用算法复杂度小于等于
#card=math&code=O%28n%5Clog%20n%29)的排序算法
快速排序
#include <cstdio>#include <iostream>const int MAXN = 1e5 + 1;int n;int ar[MAXN];int temp[MAXN];void qsort(int l, int r);int main(void) {scanf("%d", &n);for (int i = 1; i <= n; i++) {scanf("%d", ar + i);}qsort(1, n);for (int i = 1; i <= n; i++) {printf("%d ", ar[i]);}return 0;}void qsort(int l, int r) {if (l >= r) return;int mid = ar[l];int i = l;int j = r;while (i < j) {while (i < j && ar[j] >= mid) {j--;}if (i < j) {std::swap(ar[i], ar[j]);}while (i < j && ar[i] <= mid) {i++;}if (i < j) {std::swap(ar[i], ar[j]);}}qsort(l, i - 1);qsort(i + 1, r);}
归并排序
#include <cstdio>const int MAXN = 1e5 + 1;int n;int ar[MAXN];int temp[MAXN];void msort(int l, int r);int main(void) {scanf("%d", &n);for (int i = 1; i <= n; i++) {scanf("%d", ar + i);}msort(1, n);for (int i = 1; i <= n; i++) {printf("%d ", ar[i]);}return 0;}void msort(int l, int r) {if (l == r) return;int mid = (l + r) / 2;msort(l, mid);msort(mid + 1, r);int i = l;int j = mid + 1;int k = l;while (k <= mid && j <= r) {if (ar[j] < ar[k]) {temp[i++] = ar[j++];} else {temp[i++] = ar[k++];}}while (k <= mid) {temp[i++] = ar[k++];}while (j <= r) {temp[i++] = ar[j++];}for (int i = l; i <= r; i++) {ar[i] = temp[i];}}
堆排序
- 比较懒,所以用stl实现这个,优先队列默认是大根堆,我们对存入的数据取反就可以得到一个小根堆,然后取数据的时候再取反就可以对数据进行还原。大一的同学还没学过数据结构,可以先去了解一下堆的特性
#include <cstdio>#include <queue>int n;std::priority_queue<int> heap;int main(void) {scanf("%d", &n);for (int i = 1; i <= n; i++) {int temp;scanf("%d", &temp);heap.push(-temp);}while (!heap.empty()) {printf("%d ", -heap.top());heap.pop();}return 0;}
H
- 贪心经典题
- 以b排序然后冲前向后搜索不交叉的段
#include <algorithm>#include <cstdio>const int MAXN = 1e6 + 1;int n;int ans;struct Node {int a, b;int operator<(const Node node) const {return b >= node.b ? b == node.b && a < node.a ? 1 : 0 : 1;}} node[MAXN];int main(void) {scanf("%d", &n);for (int i = 1; i <= n; i++) {int a, b;scanf("%d%d", &a, &b);node[i].a = a;node[i].b = b;}std::sort(node + 1, node + 1 + n);int end = 0;for (int i = 1; i <= n; i++) {if (node[i].a >= end) {ans++;end = node[i].b;}}printf("%d", ans);return 0;}
I
#include <algorithm>#include <cstdio>#include <iostream>using namespace std;const int MAXN = 3e2 + 1;int n;struct Node {int chinese;int math;int english;int id;int operator<(const Node a) const {int total_a = chinese + math + english;int total_b = a.chinese + a.math + a.english;if (total_a < total_b) {return 0;} else if (total_a == total_b && chinese < a.chinese) {return 0;} else if (total_a == total_b && chinese == a.chinese && id > a.id) {return 0;} else {return 1;}}} stu[MAXN];int main(void) {cin >> n;for (int i = 1; i <= n; i++) {int a, b, c;cin >> a >> b >> c;stu[i].chinese = a;stu[i].math = b;stu[i].english = c;stu[i].id = i;}sort(stu + 1, stu + 1 + n);for (int i = 1; i <= 5; i++) {cout << stu[i].id << " " << stu[i].chinese + stu[i].math + stu[i].english<< endl;}return 0;}
J
#include <algorithm>#include <cmath>#include <cstdio>const int MAXN = 1e5 + 1;int n;int array_a[MAXN];int array_b[MAXN];int ans;int main(void) {scanf("%d", &n);for (int i = 1; i <= n; i++) {scanf("%d", array_a + i);}for (int i = 1; i <= n; i++) {scanf("%d", array_b + i);}std::sort(array_a + 1, array_a + 1 + n);std::sort(array_b + 1, array_b + 1 + n);for (int i = 1; i <= n; i++) {ans += abs(array_a[i] - array_b[i]);}printf("%d", ans);return 0;}
K
#include <algorithm>#include <cstdio>const int MAXN = 2e4 + 1;int n, b;int ar[MAXN];int ans;int main(void) {scanf("%d%d", &n, &b);for (int i = 1; i <= n; i++) {scanf("%d", ar + i);}std::sort(ar + 1, ar + 1 + n, std::greater<int>());int total = 0;for (int i = 1; i <= n; i++) {total += ar[i];if (total > b) {ans = i;break;}}printf("%d", ans);return 0;}
L
- 求逆序对有很多种方法因为归并排序的特性所以归并排序可以求逆序对,只需要在归并排序上添加一条语句就行,也可以使用线段树求解
#include <cstdio>const int MAXN = 1e5 + 1;int a[MAXN];int n;long long ans;int c[MAXN] = {0};void msort(int l, int r);int main(void) {scanf("%d", &n);for (int i = 1; i <= n; i++) scanf("%d", a + i);msort(1, n);printf("%lld", ans);return 0;}void msort(int l, int r) {if (l == r) return;int mid = (l + r) / 2;msort(l, mid);msort(mid + 1, r);int i = l;int j = mid + 1;int k = l;while (k <= mid && j <= r) {if (a[j] < a[k]) {c[i++] = a[j++];ans += mid - k + 1;} elsec[i++] = a[k++];}while (k <= mid) c[i++] = a[k++];while (j <= r) c[i++] = a[j++];for (int i = l; i <= r; i++) a[i] = c[i];}
M
- 贪心算法
#include <algorithm>#include <cstdio>const int MAXN = 1e3 + 1;struct array {int time;int p;} Array[MAXN];int n;int temp = 0;double ans = 0.0;bool cmp(struct array a1, struct array a2) { return a1.time < a2.time; }int main(void) {scanf("%d", &n);for (int i = 1; i <= n; i++) {scanf("%d", &Array[i].time);Array[i].p = i;}std::sort(Array + 1, Array + 1 + n, cmp);for (int i = 1; i <= n; i++) {printf("%d ", Array[i].p);temp += Array[i].time;if (i != n)ans += temp;elseputs("");}printf("%.2lf", ans / (n * 1.0));return 0;}
