由题意可轻松得知,题目中的排序方法就是冒泡排序,让我们求冒泡排序的交换次数,也就是求逆序对的个数。可以用归并排序求,也可以用树状数组来求,但是本题中的a范围较大,需要离散化,还是建议直接归并排序。
归并排序代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 5e5+10;
int n;
int a[N];
ll marge_sort(int a[],int l,int r){
if(l==r)return 0;
ll res=0;
int mid=l+r>>1;
res+=marge_sort(a,l,mid);
res+=marge_sort(a,mid+1,r);
int tmp[r-l+5],idx=0;
int i=l,j=mid+1;
while(i<=mid&&j<=r){
if(a[i]<a[j])tmp[idx++]=a[i++];
else{
res+=mid-i+1;
tmp[idx++]=a[j++];
}
}
while(i<=mid)tmp[idx++]=a[i++];
while(j<=r)tmp[idx++]=a[j++];
for(i=0;i<idx;i++)a[l+i]=tmp[i];
return res;
}
int main(){
while(cin>>n){
if(n==0)break;
for(int i=1;i<=n;i++)cin>>a[i];
cout<<marge_sort(a,1,n)<<endl;
}
return 0;
}
离散化+树状数组代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 5e5+10;
int n;
int a[N];
ll sum[N];
int lowbit(int x){
return x&-x;
}
void add(int x,int k){
for(int i=x;i<=n;i+=lowbit(i))sum[i]+=k;
}
ll query(int x){
ll res=0;
for(int i=x;i;i-=lowbit(i))res+=sum[i];
return res;
}
int main(){
while(cin>>n){
if(n==0)break;
vector<int>vec;
map<int,int>mp;
for(int i=1;i<=n;i++){
cin>>a[i];
vec.push_back(a[i]);
}
sort(vec.begin(),vec.end());
int t=vec.erase(unique(vec.begin(),vec.end()),vec.end())-vec.begin();
for(int i=0;i<t;i++)mp[vec[i]]=i+1;
memset(sum,0,sizeof (ll)*(t+5));
ll res=0;
for(int i=n;i;i--){
int x=mp[a[i]];
res+=query(x);
add(x,1);
}
printf("%lld\n",res);
}
return 0;
}