在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。
现在,给你一个N个元素的序列,请你判断出它的逆序数是多少。
比如 1 3 2 的逆序数就是1。
2 2 1 1 3 1 3 2
0 1
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define mav 1000005 int num[mav],rev[mav],n; struct node { int p,x; }nodes[mav]; int cmp(node a,node b) //注意这里,wrong了很多次,记得当值相等的时候序号的比较 { if(a.p!=b.p) return a.p<b.p; else return a.x<b.x; } int lowbit(int x) { return x&(-x); } void add(int x) { while(x<=n) { num[x]++; x+=lowbit(x); } } int sum(int x) { int total=0; while(x>0) { total+=num[x]; x-=lowbit(x); } return total; } int main() { int x,cases,i; scanf("%d",&cases); while(cases--) { scanf("%d",&n); memset( num,0,sizeof( num )); for(i=1;i<=n;i++) { scanf("%d",&nodes[i].p); nodes[i].x=i; } sort(nodes+1,nodes+n+1,cmp); for(i=1;i<=n;i++) { rev[nodes[i].x]=i; } long long int ss = 0; for(i = 1; i <=n; ++i ) { add(rev[i]); ss +=(i-sum(rev[i])); } printf("%lld\n",ss); } return 0; }
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define mav 1000002 int num[mav],rev[mav],n; struct node { int p,x; }nodes[mav]; int cmp(node a,node b) { if(a.p!=b.p) return a.p<b.p; else return a.x<b.x; } int lowbit(int x) { return x&(-x); } void add(int x) { while(x<=n) { num[x]++; x+=lowbit(x); } } int sum(int x) { int total=0; while(x) { total+=num[x]; x-=lowbit(x); } return total; } int main() { int x,cases,i; scanf("%d",&cases); while(cases--) { scanf("%d",&n); memset( num,0,sizeof(num)); memset(rev,0,sizeof(rev)); for(i=1;i<=n;i++) { scanf("%d",&x); nodes[i].p=x; nodes[i].x=i; } sort(nodes+1,nodes+n+1,cmp); for(i=1;i<=n;i++) { rev[nodes[i].x]=i; } long long int ss = 0; for(i = 1; i <=n; ++i ) { add(rev[i]); ss +=(i-1-sum(rev[i]- 1)); } printf("%lld\n",ss); } return 0; }
归并排序求逆序数
import java.util.Arrays; import java.util.Scanner; public class Main { static int a[]=new int[1000010]; static int b[]=new int[1000010]; static long sum=0; public static void merge(int a[],int begin,int end,int b[]) { if(begin==end)return ; int mid=(begin+end)/2; merge(a, begin, mid, b); merge(a, mid+1, end, b); int i=begin,j=mid+1,pos=begin; while(i<=mid&&j<=end) { if(a[i]<=a[j]) b[pos++]=a[i++]; else { b[pos++]=a[j++]; sum+=mid+1-i; } } while(i<=mid) { b[pos++]=a[i++]; } while(j<=end) { b[pos++]=a[j++]; } for(int k=begin;k<=end;k++) { a[k]=b[k]; } } public static void main(String[] args) { Scanner scanner=new Scanner(System.in); int cases=scanner.nextInt(); while(cases--!=0) { int number=scanner.nextInt(); Arrays.fill(a, 0); Arrays.fill(b, 0); sum=0; for(int i=1;i<=number;i++) { a[i]=scanner.nextInt(); } merge(a, 1, number, b); System.out.println(sum); } } }