求逆序对有三种方法:归并排序,树状数组,线段树
第一种:归并排序求逆序对
int a[N]; //需要排序的数组
int temp[N]; //中间合并用数组
ll g_nCount; //逆序对数量
void MergeArray(int l,int r,int mid) //合并两序列
{
int i=l,n=mid; //左子序列指针
int j=mid+1,m=r; //右子序列指针
int k=0; //temp数组指针
while(i<=n&&j<=m)
{
if(a[i]<=a[j])
temp[k++] = a[i++];
else
{
temp[k++] = a[j++];
//a[j]和前面每一个数都能组成逆序数对
g_nCount+=n-i+1;
}
}
while(i<=n)
temp[k++] = a[i++];
while(j<=m)
temp[k++] = a[j++];
for(int t=0;t<k;t++) //拷贝回去
a[l+t] = temp[t];
}
void Merge_sort(int l,int r) //归并排序,0~n-1的数组,则l=0,r=n-1
{
if(l<r)
{
int mid = (l+r)>>1;
Merge_sort(l,mid); //左子序列排序
Merge_sort(mid+1,r); //右子序列有序
MergeArray(l,r,mid); //两边合并
}
}
第二种:树状数组求逆序对
int tree[N];
int n;
struct node
{
int val; //输入数据的值
int id; //输入数据的位置
}a[N];
int b[N]; //离散化数组
bool cmp(node A,node B)
{
if(A.val==B.val)
return A.id<B.id;
return A.val<B.val;
}
int lowbit(int x)
{
return x & (-x);
}
int getsum(int x)
{
int res = 0;
while(x)
{
res+=tree[x];
x-=lowbit(x);
}
return res;
}
void add(int x,int val)
{
while(x<=n)
{
tree[x]+=val;
x+=lowbit(x);
}
}
void init()
{
for(int i=1;i<=n;i++)
tree[i]=0;
}
int get_reverse_pair_count()
{
init(); //初始化树状数组
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++) //离散化操作
b[a[i].id]=i; //将a[i]数组映射成更小的值
int ans=0;
for(int i=1;i<=n;i++) //更新树状数组
{
add(b[i],1); //意思是b[i]的值加1
ans+=(i-getsum(b[i])); //求得比b[i]小的个数,则i减getsum(b[i])就是前面能够和b[i]构成逆序对的数量
}
return ans;
}
第一种:线段树求逆序对
待补。