在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。
如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序数是4。给出一个整数序列,求该序列的逆序数。
Input
第1行:N,N为序列的长度(n <= 50000) 第2 - N + 1行:序列中的元素(0 <= Aii <= 10^9)
Output
输出逆序数
Sample Input
4
2
4
3
1
Sample Output
4
思路:坐标离散化+线段树;
参考模板:https://blog.csdn.net/queque_heiya/article/details/103947311
#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long ll;
const int MAX_N=50000+1;
int bit[MAX_N+1],n;
int a[MAX_N];
struct name{
int u,v;//v在这里表示id,下标
}s[MAX_N];
bool comp(const name &a,const name &b){
return a.u<b.u;
}
int sum(int i){
int s=0;
while(i>0){
s+=bit[i];
i-=i&-i;
}
return s;
}
void add(int i,int x){
while(i<=n){
bit[i]+=x;
i+=i&-i;
}
}
int main(){
while(scanf("%d",&n)!=EOF){
memset(bit,0,sizeof(bit));
for(int i=1;i<=n;i++){
cin>>s[i].u;
s[i].v=i;
}
sort(s+1,s+1+n,comp);//对结构体进行排序
for(int i=1;i<=n;i++)
a[s[i].v]=i;//离散化的过程,依次赋值1,2,3,4,...n-1,n.即对应的下标//0<=a[i]<=999,999,999数据太大不可接受
ll ans=0;
for(int j=1;j<=n;j++){
add(a[j],1);
ans+=j-sum(a[j]);
}
printf("%lld\n",ans);
}
}
queque_heiyaa 发布了167 篇原创文章 · 获赞 73 · 访问量 1万+ 私信 关注