感觉这个题还比较有启发意义:把两个数字a,b拼接起来比较a+b和b+a的大小,就会知道这两个数字所能形成的最大值了。
#include<bits/stdc++.h>
using namespace std;
string a[23];
bool cmp(string x,string y){
return x+y>y+x;
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n,cmp);
for(string s:a){
cout<<s;
}
return 0;
}
2.逆序数
排序的本质就是在消除逆序数对,这个题是对归并排序思想很好的应用。
归并排序模板:
#include <iostream>
using namespace std;
int a[2010], b[2010];
void merge_(int l, int r, int mid) { //函数定义为合并两个有序的区间
int p = l, q = mid + 1;
for (int i = l; i <= r; i++) {
if (q > r || p <= mid && a[p] <= a[q]) { //这里要先判断q是否越界
b[i] = a[p++];
}
else {
b[i] = a[q++];
}
}
for (int i = l; i <= r; i++) {
a[i] = b[i];
}
}
void merge_sort(int l, int r) { //函数定义为把[l,r]变成有序的
if (l == r) return;
int mid = (l + r) / 2;
merge_sort(l, mid);
merge_sort(mid + 1, r);
merge_(l, r, mid);
}
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
merge_sort(0, n - 1);
for (int i = 0; i < n; i++) {
cout << a[i]<<" ";
}
return 0;
}
对这个模板稍作修改就能解出此题:
#include <iostream>
#include<algorithm>
#include<string>
using namespace std;
int a[2010], b[2010];
int cnt=0;
/*
假设现在左右区间分别为
1 3 5 7 ----2 4 6 8
当a[q]<a[p]时,说明a[p]到a[mid]的数都可以和a[q]构成逆序对
共mid-p+1对
*/
void merge_(int l, int r, int mid) {
int p = l, q = mid + 1;
for (int i = l; i <= r; i++) {
if (q > r || p <= mid && a[p] <= a[q]) {
b[i] = a[p++];
}
else {
b[i] = a[q++];
cnt+=mid-p+1; //cnt+=的原因是每消除一个逆序对,cnt就要加上
}
}
for (int i = l; i <= r; i++) {
a[i] = b[i];
}
}
void merge_sort(int l, int r) {
if (l == r) return;
int mid = (l + r) / 2;
merge_sort(l, mid);
merge_sort(mid + 1, r);
merge_(l, r, mid);
}
int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
merge_sort(0, n - 1);
cout<<cnt;
return 0;
}