一、直接调用快排sort函数
P2676 [USACO07DEC]Bookshelf B
#include <bits/stdc++.h>
using namespace std;
int n, b, h[20001], s;
int main()
{
scanf("%d %d", &n, &b);
for(int i=1; i<=n; ++i){
scanf("%d", &h[i]);
}
sort(h+1, h+n+1);
for(int i=n; i>=1; --i){
s+=h[i];
if(s>=b){
printf("%d", n-i+1);
return 0;
}
}
return 0;
}
一、字符串高精度排序
P1781 宇宙总统
#include <bits/stdc++.h>
using namespace std;
int n, asd;
string x, mx;
//如果a > b, 则返回true
bool cmp(string a, string b)
{
int l1=a.length(), l2=b.length();
if(l1==l2) //如果长度一样
{
for(int i=0; i<l1; ++i){
if(a[i]>b[i]){ //a>b
return true;
}
else if(a[i]<b[i]){ //a<b
return false;
}
}
//相等
return false;
}
else{ //如果长度不同, 长度长的大
return l1>l2;
}
}
int main()
{
scanf("%d", &n);
for(int i=1; i<=n; ++i){
cin >> x;
//如果x比mx还要大
if(cmp(x, mx)){
mx=x;
asd=i;
}
}
printf("%d\n", asd);
cout << mx;
return 0;
}
二、桶排序
P1271 【深基9.例1】选举学生会
//桶排序模板题
#include <bits/stdc++.h>
using namespace std;
int n, m, x, tong[1000];
int main()
{
scanf("%d %d", &n, &m);
for(int i=1; i<=m; ++i){
scanf("%d", &x);
tong[x]++;
}
for(int i=1; i<=n; ++i){
for(int j=1; j<=tong[i]; ++j){
printf("%d ", i);
}
}
return 0;
}
三、根据结构体某一元素排序
P5143 攀爬者
#include <bits/stdc++.h>
using namespace std;
int n;
double ans;
struct node{
double x, y, z;
}a[50006];
bool cmp(node p, node q)
{
return p.z<q.z;
}
double dis(node p, node q)
{
double xx1=p.x, yy1=p.y, zz1=p.z, xx2=q.x, yy2=q.y, zz2=q.z;
return sqrt((xx1-xx2)*(xx1-xx2)+(yy1-yy2)*(yy1-yy2)+(zz1-zz2)*(zz1-zz2));
}
int main()
{
scanf("%d", &n);
for(int i=1; i<=n; ++i){
scanf("%lf %lf %lf", &a[i].x, &a[i].y, &a[i].z);
}
sort(a+1, a+n+1, cmp);
for(int i=1; i<n; ++i){
ans+=dis(a[i], a[i+1]);
}
printf("%.3lf", ans);
return 0;
}
四、归并排序
归并排序模板
//归并排序O(nlogn)
#include <bits/stdc++.h>
using namespace std;
int n, a[500006], temp[500006];
void f(int l, int r)
{
if(l>=r) return;
int mid=(l+r)>>1;
f(l, mid);
f(mid+1, r);
int head1=l, head2=mid+1;
for(int i=l; i<=r; ++i){
//当head2没有超出r, 并且右区间第一个数比左区间第一个数小
//或者当head2没有超出r,右区间已经空了
//则将右区间的第一个数放入temp数组中
if(head2<=r && (head1>mid || a[head2]<a[head1])){
temp[i]=a[head2];
head2++;
}
else{
temp[i]=a[head1];
head1++;
}
}
for(int i=l; i<=r; ++i){
a[i]=temp[i];
}
return;
}
int main()
{
scanf("%d", &n);
for(int i=1; i<=n; ++i){
scanf("%d", &a[i]);
}
f(1, n);
for(int i=1; i<=n; ++i){
printf("%d ", a[i]);
}
return 0;
}
P1908 逆序对(归并排序思想)
//归并排序思路求逆序对个数O(nlogn)
#include <bits/stdc++.h>
using namespace std;
int n, a[500006], temp[500006];
long long ans;
//计算a[l~r]中的逆序对数量
void f(int l, int r)
{
if(l>=r) return;
int mid=(l+r)>>1;
//先往下分
f(l, mid);
f(mid+1, r);
//再不断合并
int head1=l, head2=mid+1;
for(int i=l; i<=r; ++i){
//当head2没有超出r, 并且右区间第一个数比左区间第一个数小
//或者当head2没有超出r,右区间已经空了
//则将右区间的第一个数放入temp数组中
if(head2<=r && (head1>mid || a[head2]<a[head1])){
temp[i]=a[head2];
head2++;
//当右区间a[head2]比左区间a[head1]小时, a[head2]会比a[head1~mid]都要小,
//此时a[head2]这个数会给答案贡献 mid-head1+1
ans+=mid-head1+1;
}
else{
temp[i]=a[head1];
head1++;
//或者当左区间a[head1]要放入temp数组中时, 要形成逆序对,
//只需要在右区间找比它小的数的个数, 也就是右区间中在它(a[head1])之前已经放入temp数组中的数
//就是mid+1~head2-1这些数, 总数为 head2-1-(mid+1)+1=head2-mid-1
// ans+=head2-mid-1;
}
}
for(int i=l; i<=r; ++i){
a[i]=temp[i];
}
return;
}
int main()
{
scanf("%d", &n);
for(int i=1; i<=n; ++i){
scanf("%d", &a[i]);
}
f(1, n);
printf("%lld", ans);
return 0;
}
P1966 [NOIP2013 提高组] 火柴排队(归并排序求逆序对数量)
//求∑(ai-bi)^2的最小值, 相当于求 ∑(ai*bi)的最大值
//当a[]从大到小排序, b[]从大到小排序后, ∑(ai*bi)的值最大
//或者当a[]从小到大排序, b[]从小到大排序后, ∑(ai*bi)的值最大
//排好序的两个数组中第i位上的两个数一一对应即为最终的状态,
//但是并不需要全部排序, 只要满足一一对应关系即可, 这样能减少交换次数
//因为数据范围2^31-1比较大, 所以需要离散化一下
#include <bits/stdc++.h>
#define mod 99999997
using namespace std;
int n, c[100006], temp[100006];
long long ans;
struct asd
{
int height, id;
}a[100006], b[100006];
//按照height从小到大排序
bool cmp(asd x, asd y)
{
return x.height<y.height;
}
void f(int l, int r)
{
if(l>=r) return;
int mid=(l+r)>>1;
f(l, mid);
f(mid+1, r);
int head1=l, head2=mid+1, cnt=l;
while(head1<=mid && head2<=r){
if(c[head1]<c[head2]){
temp[cnt]=c[head1];
cnt++;
head1++;
}
else if(c[head1]>c[head2]){ //如果左区间的c[head1]大于右区间的c[head2]
//逆序对, 那么左区间的c[head1~mid]一定大于右区间c[heade2]
ans=(ans+mid-head1+1)%mod;
temp[cnt]=c[head2];
cnt++;
head2++;
}
}
while(head1<=mid){
temp[cnt]=c[head1];
cnt++;
head1++;
}
while(head2<=r){
temp[cnt]=c[head2];
cnt++;
head2++;
}
for(int i=l; i<=r; ++i){
c[i]=temp[i];
}
return;
}
int main()
{
scanf("%d", &n);
for(int i=1; i<=n; ++i){
scanf("%d", &a[i].height);
a[i].id=i; //离散化
}
for(int i=1; i<=n; ++i){
scanf("%d", &b[i].height);
b[i].id=i; //离散化
}
//根据height从小到大排序
sort(a+1, a+n+1, cmp);
sort(b+1, b+n+1, cmp);
//a[1~n].height需要和b[1~n].height一一对应
//也就是a[1~n].id需要和b[1~n].id一一对应
//那我们让a[]数组不动, 我们去动b[]数组, 来和a[]数组一一对应上
//这时候需要做一个映射
for(int i=1; i<=n; ++i){
c[a[i].id]=b[i].id;
}
//归并排序找逆序对
f(1, n);
printf("%lld", ans);
return 0;
}