排序

summary:

用好\(sort\)万事大吉

可以康康归并排序逆序对——当然还是觉得树状数组求逆序对更简单

冒泡排序

原理

冒泡排序是一种交换排序,它的基本思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序的记录为止。

https://zhuanlan.zhihu.com/p/61094267

复杂度最好\(O(n)\)——本身有序

最差\(O(N^2)\)——本身逆序

优化

优化

例题

https://www.luogu.com.cn/problem/P4378

Description

进行多少次冒泡排序

Solution

转载自https://www.cnblogs.com/Hs-black/p/11626111.html

博客后还有别的证明方法

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=4e6+10;
inline int read() {
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int n,m,cnt;
int b[N],c[N];
pair<int,int>a[N];
void update(int x){
    for(;x<=N;x+=x&(-x))
        c[x]++;
}
int query(int x){
    int res=0;
    for(;x;x-=x&(-x))
        res+=c[x];
    return res;
}
int ans;
bool cmp(pair<int,int> a,pair<int,int> b){
    return a.second<b.second;
}
int main(){
    n=read();
    for(int i=1;i<=n;i++) a[i]=make_pair(read(),i);
    sort(a+1,a+1+n);
    for(int i=1;i<=n;i++) a[i].first=i;
    sort(a+1,a+1+n,cmp);
    for(int i=1;i<=n;i++){
        update(a[i].first);
        ans=max(ans,i-query(a[i].first));
    }
    printf("%d\n",ans+1);
    return 0;
}

直接插入排序

类似于斗地主整理手牌

希尔排序

没啥用吧

快速排序

常用的

一趟排序基准元素就在它正确的位置,然后递归处理它前面的和后面的,

void qsort(int a[],int l,int r){
    if((l<r){
        int i=l,j=r,x=a[l];
        while(i<j){
            while(i<j&&a[j]>=x) j--;
            if(i<j) a[i++]=a[j];
            while(i<j&&a[i]<x) i++;
            if(i<j) a[j--]=a[i];
        }
        a[i]=x;
        qsort(a,l,i-1);
        qsort(a,i+l,r);
    }
}

一般用好\(sort\)就万事大吉

选择排序

直观

归并排序

\(O(nlogn)\)

\[T(n)=2*T(n/2)+n;\\ 设m=2^k,k=logm;则有 T(n)=2*T(n/2)+n=2*T(2*T(n/4)+n/2)+n...\\ 2^k*T(1)+k*m=m+m*logm;\\ \]

递归树\(log\)层,每层合并是\(n\)

求逆序对

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=1e6;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int n;
long long a[N],c[N],ans;
void merge(int l,int r){
    if(l>=r) return;
    int mid=(l+r)>>1;
    merge(l,mid);
    merge(mid+1,r);
    for(int i=l;i<=r;i++) c[i]=a[i];
    int i=l,j=mid+1;
    for(int k=l;k<=r;k++){
        if(i>mid) a[k]=c[j++];
        else if(j>r) a[k]=c[i++];
        else if(c[i]>c[j]) a[k]=c[j++],ans+=mid-i+1;//和j产生的逆序对数量
        else a[k]=c[i++];
    }
}
int main(){
    n=read();
    for(int i=1;i<=n;i++)
        a[i]=read();
    merge(1,n);
    printf("%lld\n",ans);
    return 0;
} 


posted @ 2020-08-22 10:26  ke_xin  阅读(17)  评论(0编辑  收藏  举报