码迷,mamicode.com
首页 > 其他好文 > 详细

逆序对

时间:2020-07-14 21:51:19      阅读:65      评论:0      收藏:0      [点我收藏+]

标签:ons   clu   cpp   离散化   main   归并   its   ref   ble   

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

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

代码:

#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\n",&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\n",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

排序

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

逆序对

标签:ons   clu   cpp   离散化   main   归并   its   ref   ble   

原文地址:https://www.cnblogs.com/RadestionAdtinium/p/13301267.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!