概念
逆序对,是什么?
一个数组 a,如果 a [ i ] > a [ j ] 并且 i < j,那么称 a [ i ] 和 a [ j ] 是逆序对。
举个例子:
这里有一个数组:a [ 5 ] = { 1 , 3 , 4 , 2 , 5 }
那么,数组中的3和2、4和2都是逆序对
题目练习
基础逆序对计数

cpp
#include <bits/stdc++.h>
using namespace std;
int n,a[1010];
int main()
{
cin>>n;
for(int i = 1;i<=n;i++)
{
cin>>a[i];
}
int cnt = 0;
for(int i = 1;i<=n-1;i++)
{
for(int j = 1;j<=n-i;j++)
{
if(a[j]>a[j+1])
{
// cout<<a[j]<<" "<<a[j+1]<<endl;
swap(a[j],a[j+1]);
cnt++;
}
}
}
// for(int i = 1;i<=n;i++)
// {
// cout<<a[i]<<" ";
// }
// cout<<endl;
cout<<cnt;
return 0;
}
插入排序优化

cpp
#include <bits/stdc++.h>
using namespace std;
int n,a[1010];
int main()
{
cin>>n;
for(int i = 1;i<=n;i++)
{
cin>>a[i];
}
int cnt = 0;
for(int i = 2;i<=n;i++)
{
int t = a[i];
int j = i-1;
for(;j>=1;j--)
{
if(a[j]>t) a[j+1] = a[j],cnt++;
else break;
}
a[j+1] = t;
// cout<<i<<" "<<j<<" "<<cnt<<endl;
// for(int i = 1;i<=n;i++)
// {
// cout<<a[i]<<" ";
// }
// cout<<endl;
}
// for(int i = 1;i<=n;i++)
// {
// cout<<a[i]<<" ";
// }
cout<<cnt;
return 0;
}
大规模数据的逆序对计数

cpp
#include <bits/stdc++.h>
using namespace std;
int n,a[100010];
int cnt;
void guibing(int,int);
int main()
{
cin>>n;
for(int i = 1;i<=n;i++)
{
cin>>a[i];
}
guibing(1,n);
// for(int i = 1;i<=n;i++)
// {
// cout<<a[i]<<" ";
// }
// cout<<endl;
cout<<cnt;
return 0;
}
void guibing(int l,int r)
{
if(l==r) return;
int mid = (l+r)/2;
guibing(l,mid);
guibing(mid+1,r);
int i = l;
int j = mid+1;
int t[100010] = {0};
int lt = l-1;
while(i<=mid&&j<=r)
{
if(a[j]<a[i])
{
cnt += mid-i+1;
t[++lt] = a[j];
j++;
}
else
{
t[++lt] = a[i];
i++;
}
}
while(i<=mid)
{
t[++lt] = a[i];
i++;
}
while(j<=r)
{
t[++lt] = a[j];
j++;
}
// cout<<l<<" "<<mid<<" "<<r<<" "<<cnt<<endl;
for(int ii = l;ii<=r;ii++)
{
a[ii] = t[ii];
}
return;
}
最小逆序对

cpp
#include <bits/stdc++.h>
using namespace std;
int n,a[100010],b[100010];
int cnt,mi;
void guibing(int,int);
int main()
{
cin>>n;
for(int i = 1;i<=n;i++)
{
cin>>b[i];
}
mi = 999999999;
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=i;j++)
{
a[n-i+j] = b[j];
}
for(int j = 1;j<=n-i;j++)
{
a[j] = b[i+j];
}
guibing(1,n);
mi = min(mi,cnt);
cnt = 0;
}
// for(int i = 1;i<=n;i++)
// {
// cout<<a[i]<<" ";
// }
// cout<<endl;
cout<<mi;
return 0;
}
void guibing(int l,int r)
{
if(l==r) return;
int mid = (l+r)/2;
guibing(l,mid);
guibing(mid+1,r);
int i = l;
int j = mid+1;
int t[100010] = {0};
int lt = l-1;
while(i<=mid&&j<=r)
{
if(a[j]<a[i])
{
cnt += mid-i+1;
t[++lt] = a[j];
j++;
}
else
{
t[++lt] = a[i];
i++;
}
}
while(i<=mid)
{
t[++lt] = a[i];
i++;
}
while(j<=r)
{
t[++lt] = a[j];
j++;
}
// cout<<l<<" "<<mid<<" "<<r<<" "<<cnt<<endl;
for(int ii = l;ii<=r;ii++)
{
a[ii] = t[ii];
}
return;
}