AIRobot

AIRobot quick note


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 搜索

求排列的逆序数

发表于 2018-12-25 分类于 algorithm
本文字数: 1.3k 阅读时长 ≈ 1 分钟
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
总时间限制: 1000ms 内存限制: 65536kB 
描述
在Internet上的搜索引擎经常需要对信息进行比较,比如可以通过某个人对一些事物的排名来估计他(或她)对各种不同信息的兴趣,从而实现个性化的服务。

对于不同的排名结果可以用逆序来评价它们之间的差异。考虑1,2,…,n的排列i1,i2,…,in,如果其中存在j,k,满足 j < k 且 ij > ik, 那么就称(ij,ik)是这个排列的一个逆序。

一个排列含有逆序的个数称为这个排列的逆序数。例如排列 263451 含有8个逆序(2,1),(6,3),(6,4),(6,5),(6,1),(3,1),(4,1),(5,1),因此该排列的逆序数就是8。显然,由1,2,…,n 构成的所有n!个排列中,最小的逆序数是0,对应的排列就是1,2,…,n;最大的逆序数是n(n-1)/2,对应的排列就是n,(n-1),…,2,1。逆序数越大的排列与原始排列的差异度就越大。

现给定1,2,…,n的一个排列,求它的逆序数。

输入
第一行是一个整数n,表示该排列有n个数(n <= 100000)。
第二行是n个不同的正整数,之间以空格隔开,表示该排列。
输出
输出该排列的逆序数。
样例输入
6
2 6 3 4 5 1
样例输出
8

对于冒泡排序,交换次数就是逆序对数
归并排序时,归并操作时统计左边数组中小于右边数组元素的个数。
增加一句ans+=mid-i+1;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<iostream>
#include<cstdio>
#define N 100010
using namespace std;

int n,a[N],b[N];
long long ans;

void merge_sort(int l,int r)
{
if(l==r) return;
int mid=(l+r)/2,i,j,k;
i=l;k=l;j=mid+1;
merge_sort(l,mid);
merge_sort(mid+1,r);
while(i<=mid && j<=r)
{
if(a[i]<=a[j])
b[k++]=a[i++];
else
ans+=mid-i+1,b[k++]=a[j++];
}
while(i<=mid)
b[k++]=a[i++];
while(j<=r)
b[k++]=a[j++];
for(int o=l;o<=r;++o)
a[o]=b[o];
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
merge_sort(1,n);
for(int i=1;i<=n;++i)
printf("%d ",a[i]);
printf("\n%lld\n",ans);
return 0;
}
LeetCode 3 无重复字符的最长子串
装箱问题
AIRobot

AIRobot

AIRobot quick note
130 日志
15 分类
23 标签
GitHub E-Mail
Creative Commons
0%
© 2023 AIRobot | 716k | 10:51