逆序对
定义
设 A 为一个有 n 个数字的有序集 (n>1),其中所有数字各不相同。
如果存在正整数 i, j 使得 1 ≤ i < j ≤ n 而且 A[i] > A[j],则 <A[i], A[j]> 这个有序对称为 A 的一个逆序对,也称作逆序数。
实现
归并排序
在归并排序中,利用cnt计数即可。
void mergeArray(int arr[],int first,int mid,int last)
{
int i=first,j=mid+1,m=mid,n=last,k=0,temp[maxn];
while(i<=m&&j<=n)
{
if(arr[i]<=arr[j]) temp[k++]=arr[i++];
else temp[k++]=arr[j++],cnt+=m-i+1;
}
while(i<=m) temp[k++]=arr[i++];
while(j<=n) temp[k++]=arr[j++];
for(i=0;i<k;i++) arr[first+i]=temp[i];
}
void mySort(int arr[],int first,int last)
{
if(first<last)
{
int mid=(first+last)/2;
mySort(arr,first,mid);
mySort(arr,mid+1,last);
mergeArray(arr,first,mid,last);
}
}
树状数组
线段树也不是不行。-O-O-
#include<bits/stdc++.h>
using namespace std;
const int maxn=500100;
struct node
{
int w,id;
node(){}
node(int a,int b){id=a;w=b;}
bool operator<(const node &n) const
{
if(w!=n.w) return w>n.w;
else return id>n.id;
}
}w[maxn];
int tree[maxn],n;
int lowbit(int x);
int check(int x);
void update(int x);
int main()
{
int i,x;
long long ans=0;;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&x);
w[i]=node(i,x);
}
sort(w+1,w+1+n);
for(i=1;i<=n;i++)
{
ans+=check(w[i].id);
update(w[i].id);
}
printf("%lld\n",ans);
return 0;
}
int lowbit(int x)
{return x&(-x);}
int check(int x)
{
int ans=0;
for(;x>0;x-=lowbit(x)) ans+=tree[x];
return ans;
}
void update(int x)
{
for(;x<=n;x+=lowbit(x)) tree[x]++;
}