day06
今天看了快排和归并排序
归并排序里这个逆序对还是有点意思的
题目:
给定一个长度为 n
的整数数列,请你计算数列中的逆序对的数量。
逆序对的定义如下:对于数列的第 i
个和第 j
个元素,如果满足 i<j
且 a[i]>a[j]
,则其为一个逆序对;否则不是。
输入格式
第一行包含整数 n
,表示数列的长度。
第二行包含 n
个整数,表示整个数列。
输出格式
输出一个整数,表示逆序对的个数
数据范围
1≤n≤100000
数列中的元素的取值范围 [1,109]
输入样例:
6
2 3 4 5 6 1
输出样例:
5
代码如下:
include
using namespace std;
const int N=1e6+10;
int q[N],tmp[N];
long long result=0;
void merge_sort(int q[],int l,int r) //归并排序是从中间分开,两个数组最小数依次比较,将最小数放入临时数组,最后将临时数组放回原数组;
{
if(l>=r)return;
int mid=(l+r)/2;
merge_sort(q,l,mid);
merge_sort(q,mid+1,r);
int i=l,j=mid+1,k=0;
while(i<=mid&&j<=r)
{
if(q[i]<=q[j])tmp[k++]=q[i++]; //比较值q[i]与q[j],而不是比较i,j;
else {
tmp[k++]=q[j++];
result+=(mid-i+1);//就是相当于归并排序模板加了一行这个,大致就是分为左右两部分;
//每次左数组的最小数与右数组对比,若大,则左数组全部数大于右数组,即左数组个数即为逆序对个数;
//然后去掉左数组的最小数放入临时数组;
//若小,则直接放入临时数组,然后依次循环;
}
}
while(i<=mid)tmp[k++]=q[i++];
while(j<=r)tmp[k++]=q[j++];
for(int i=l,j=0;i<=r;i++,j++)
q[i]=tmp[j];
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
scanf("%d",&q[i]);
merge_sort(q,0,n-1);
cout<<result;
return 0;
}
明天看高精度加减乘除qaq
浙公网安备 33010602011771号