题目描述
对于一个包含N个非负整数的数组A[1…n],如果有i < j,且A[ i ]>A[ j ],则称(A[ i] ,A[ j] )为数组A中的一个逆序对。 例如,数组(3,1,4,5,2)的逆序对有(3,1),(3,2),(4,2),(5,2),共4个。
求n个数中的逆序对个数。
输入
第一行一个整数n(<=1,000,000)
第二行n个整数,a[i]<=2^31-1
输出
n个数中逆序对个数
样例输入
5
3 1 4 5 2
样例输出
4
1.我们可以使用归并排序
为什么使用递归?
answer:要使用归并排序首先就要将数据分解,一直分解到每一个单位,然后就是进行合并了;
如何合并?
answer:比较ai,aj的大小。其中ai 属于左区间,aj属于右区间,其实就是将左右区间合并、并排序),若ai<aj ,则将ai复制到r[k]中,然后将i和k都加1,否则将aj
复制到r[k]中,将j,k加1,最后再将r[k]移动到ai中,然后继续合并;
下面归并排序的逆序对写法:
#include<bits/stdc++.h>
using namespace std;
int n;
long long ans;
int arr[1000005];
int arr1[1000005];
void Merge(int l,int r,int mid){
int i=l;
int j=mid+1;
int k=l;
while(i<=mid&&j<=r){
if(arr[i]<=arr[j])
arr1[k++]=arr[i++];
else
arr1[k++]=arr[j++],ans+=mid-i+1;
}
if(i<=mid)
while(i<=mid)
arr1[k++]=arr[i++];
else
while(j<=r)
arr1[k++]=arr[j++];
for(int m=l;m<=r;m++)
arr[m]=arr1[m];
}
void Merge_sort(int l,int r){
if(l<r){
int mid=l+(r-l)/2;
Merge_sort(l,mid);
Merge_sort(mid+1,r);
Merge(l,r,mid);
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&arr[i]);
Merge_sort(1,n);
printf("%lld",ans);
return 0;
}
2.线段树求法:
在这里,我们需要先离散化一下,然后到着插入线段树(n-1),每次在线段树中查找比他小的值有几个(ans加上他),再将当前a[i]的值在线段树上加一,最后输出就行了
代码:
#include<bits/stdc++.h>
using namespace std;
int n;
long long ans;
long long b[1000005];
long long a[1000005];
long long tree[4000005];
struct node{
long long val;
int id;
}x[1000005];
int query(int p,int l,int r,int x,int y){
if(l==x&&r==y)
return tree[p];
int mid=l+(r-l)/2;
if(y<=mid)
return query(p+p,l,mid,x,y);
else if(x>mid)
return query(p+p+1,mid+1,r,x,y);
else
return query(p+p,l,mid,x,mid)+query(p+p+1,mid+1,r,mid+1,y);
}
void Insert(int p,int l,int r,int x,int val){
if(l==r){
tree[p]+=val;
return;
}
int mid=l+(r-l)/2;
if(x<=mid)
Insert(p+p,l,mid,x,val);
else
Insert(p+p+1,mid+1,r,x,val);
tree[p]=tree[p+p]+tree[p+p+1];
}
bool cmp(node a,node b){
return a.val<b.val;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
x[i].val=a[i];
x[i].id=i;
}
sort(x+1,x+n+1,cmp); //离散化
b[1]=1;
x[0].val=983478348;
for(int i=2;i<=n;i++){
if(x[i].val==x[i-1].val)
b[i]=b[i-1];
else
b[i]=b[i-1]+1;
}
for(int i=1;i<=n;i++)
a[x[i].id]=b[i];
for(int i=n;i>=1;i--){
ans+=query(1,0,n,0,a[i]-1);
Insert(1,0,n,a[i],1);
}
printf("%lld",ans);
return 0;
}