当前位置: 代码迷 >> 综合 >> 51Nod--1019--逆序对数--线段树
  详细解决方案

51Nod--1019--逆序对数--线段树

热度:16   发布时间:2023-12-12 06:30:54.0

在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。

如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);} 
}