求逆序对
Description
给定一个序列a1,a2,…,an,如果存在i<j并且ai>aj,那么我们称之为逆序对,求逆序对的数目。
Input
第一行为n,表示序列长度,接下来的一行包含n个整数(A1,A2,…,An),表示序列中的n个数。
N<=10^5
,Ai<=10^5,
Ai<= 10^5
Output
输出所有逆序对总数。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<stdlib.h>
#include<stack>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[100005]= {0};
int c[100005]={0};
long long int sum=0;
void hhhh(int left,int right)
{
if(left<right)
{
int mid=(left+right)/2;
hhhh(left,mid);
hhhh(mid+1,right);
int l1=left;
int l2=mid+1;
int h=left;
while(l1<=mid&&l2<=right)
{
if(a[l1]<=a[l2])
//判断有无逆序对,且用c[]将a[left]到a[right]段升序排序
{
c[h]=a[l1];
l1++;
}
else
{
c[h]=a[l2];
l2++;
sum+=mid-l1+1;
//a[l1]比a[l2]大,说明后面的a[l1]到a[mid]都比a[l2]大
}
h++;
}
while(l1<=mid)
c[h++]=a[l1++];
while(l2<=right)
c[h++]=a[l2++];
for(int i=left; i<=right; i++)
a[i]=c[i];
//此时left到right段的逆序对都加了进去,将这一段的数组升序排序了
}
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
hhhh(1,n);
cout<<sum<<endl;
sum=0;
}
}
比如数列4
3 2 3 2
①3 2 3 2
分为3 2,3 2;
left为1,right为4,mid为2;
进入两个hhhh里面,
②left为1,right为2,mid为1;
3 2为一个逆序对,sum+=1-1+1;然后利用c[]再排序,a[1]为2,a[2]为3.
同理:a[3]为2,a[4]为3;sum+=3-3+1;
③数组为2 3 2 3分为两块:2 3, 2 3
l1=1,l2=3;
再进行比较,2比2——>l1++;l1=2
3比2——>l2++,l2=4
sum+=2-2+1;
所以所有的数组都是被分成了一个个小区间,然后两两合并。比较两个区间里面的数组元素