逆序对

Posted radestionadtinium

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了逆序对相关的知识,希望对你有一定的参考价值。

逆序对目前我所知的有三种解法

首先是最简单的冒泡排序,当每次前面一个数比后面一个数大时就会交换,因此可以用冒泡排序来求逆序对

代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,sum=0;
	cin>>n;
	int a[10001];
	for(int i=1;i<=n;i++) scanf("%d
",&a[i]);
	for(int i=1;i<=n;i++)
	    for(int j=i+1;j<=n;j++)
	        if(a[i]>a[j]) sum++;
	printf("%d",sum);
	return 0;
}

两个(for)循环,复杂度为(O(n^2))


接下来是归并排序,由于每次(merge)的时候会判断数的大小,所以归并排序可以用来求逆序对

代码:

#include<cstdio>
#define ll long long 
using namespace std;
const int maxn=5e5+5;

int a[maxn],r[maxn],n;
ll ans=0;
void msort(int s,int t){
	if(s==t) return ;
	int mid=s+t>>1;
	msort(s,mid),msort(mid+1,t);
	int i=s,j=mid+1,k=s;
	while(i<=mid&&j<=t)
		if(a[i]<=a[j]) r[k++]=a[i++];
		else r[k++]=a[j++],ans+=(ll)mid-i+1;
	while(i<=mid) r[k]=a[i],k++,i++;
	while(j<=t) r[k]=a[j],k++,j++;
	for(int i=s;i<=t;i++) a[i]=r[i]; 
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	msort(1,n);
	printf("%lld
",ans);
	return 0;
}

复杂度为(O(nlogn))


最后是树状数组的解法

首先需要把数组离散化,然后从小到大排序,加入树状数组里维护

由于排完序是从小到大丢到树状数组里面的

所以现在加入的数字一定比之后加入的数字大

查询这个数前面的数就可以求得逆序对的个数了

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=500005;
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch==‘-‘) f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}
ll n,a[N],b[N],f[N],ans;
inline bool cmp(const ll &i,const ll &j){return b[i]>=b[j];}
inline ll lowbit(ll x){return x&-x;}
inline void add(ll x){while(x<=n) ++f[x],x+=lowbit(x);return;}
inline void query(ll x){while(x) ans+=f[x],x-=lowbit(x);return;}
int main(){
    n=read();
    for(ll i=1;i<=n;++i) b[i]=read(),a[i]=i;
    stable_sort(a+1,a+1+n,cmp);
    for(ll i=1;i<=n;++i) add(a[i]),query(a[i]-1);
    printf("%lld",ans);
    return 0;
}

复杂度为(O(nlogn))


推荐使用树状数组,毕竟树状数组能做的东西比归并排序多,但是两种方式都是必须要掌握的

一些练习题:

逆序对

火柴排队

LIT-Letters

排序

如果能把这些题目都写完了,那么您对逆序对一定掌握的非常熟练了

以上是关于逆序对的主要内容,如果未能解决你的问题,请参考以下文章

c++ 逆序对

第三次过程性考核

逆序对的求解逆序对个数问题

递归逆序的使用

逆序对

树状数组求逆序对