求逆序对有三种方法:归并排序,树状数组,线段树
第一种:归并排序求逆序对
int a[N]; //需要排序的数组 int temp[N]; //中间合并用数组 ll g_nCount; //逆序对数量 void MergeArray(int l,int r,int mid) //合并两序列 { int i=l,n=mid; //左子序列指针 int j=mid+1,m=r; //右子序列指针 int k=0; //temp数组指针 while(i<=n&&j<=m) { if(a[i]<=a[j]) temp[k++] = a[i++]; else { temp[k++] = a[j++]; //a[j]和前面每一个数都能组成逆序数对 g_nCount+=n-i+1; } } while(i<=n) temp[k++] = a[i++]; while(j<=m) temp[k++] = a[j++]; for(int t=0;t<k;t++) //拷贝回去 a[l+t] = temp[t]; } void Merge_sort(int l,int r) //归并排序,0~n-1的数组,则l=0,r=n-1 { if(l<r) { int mid = (l+r)>>1; Merge_sort(l,mid); //左子序列排序 Merge_sort(mid+1,r); //右子序列有序 MergeArray(l,r,mid); //两边合并 } }
第二种:树状数组求逆序对
int tree[N]; int n; struct node { int val; //输入数据的值 int id; //输入数据的位置 }a[N]; int b[N]; //离散化数组 bool cmp(node A,node B) { if(A.val==B.val) return A.id<B.id; return A.val<B.val; } int lowbit(int x) { return x & (-x); } int getsum(int x) { int res = 0; while(x) { res+=tree[x]; x-=lowbit(x); } return res; } void add(int x,int val) { while(x<=n) { tree[x]+=val; x+=lowbit(x); } } void init() { for(int i=1;i<=n;i++) tree[i]=0; } int get_reverse_pair_count() { init(); //初始化树状数组 sort(a+1,a+1+n,cmp); for(int i=1;i<=n;i++) //离散化操作 b[a[i].id]=i; //将a[i]数组映射成更小的值 int ans=0; for(int i=1;i<=n;i++) //更新树状数组 { add(b[i],1); //意思是b[i]的值加1 ans+=(i-getsum(b[i])); //求得比b[i]小的个数,则i减getsum(b[i])就是前面能够和b[i]构成逆序对的数量 } return ans; }
第一种:线段树求逆序对
待补。