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

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

如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);
	} 
}
发布了170 篇原创文章 · 获赞 73 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/queque_heiya/article/details/104550151
今日推荐