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 <= A[i] <= 10^9)
Output
输出逆序数
Input示例
4 2 4 3 1
Output示例
4
思路:
本题的题意较为简单,起初一组数中的逆序对的数量。其中的关键是对离散化的理解。离散化在这个过程中感觉更像是在记录了原来的先后顺序的情况下按照数值大小再次排序,这样在判断逆序对的时候可以以n的复杂度顺序判断,而不需要n^2判断。
AC代码:
#include <stdio.h> #include <algorithm> #include <iostream> using namespace std; const int maxn=50005; int n; int hash[maxn]; struct Node{ int s,v; }node[maxn]; int tree[maxn]; bool cmp(Node a,Node b){ return a.v<b.v; } int lowbit(int i){ return i&(-i); } void add(int x,int v){ for(int i=x;i<=n;i+=lowbit(i)){ tree[i]+=v; } } int getsum(int i){ int s=0; while(i>0){ s+=tree[i]; i-=lowbit(i); } return s; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&node[i].v); node[i].s=i; } //离散化 ,hash[i]里存的是v的值为i的node在全部node中以v排序后的排名 (由小到大) sort(node+1,node+1+n,cmp); for(int i=1;i<=n;i++){ hash[node[i].s]=i; } int res=0; for(int i=1;i<=n;i++){ add(hash[i],1); res+=i-getsum(hash[i]); } cout<<res; return 0; }