粒子实验
时问限制:3000ms
内存限制:589824kb
题目描述:
一些科学家在研究X粒子的特性,通常情况下,X粒子在经过加速装置后拥有的速度均为V,但是加热后,某些粒子的特性发生了变化,在相同情况下经过加速装置后拥有的速度变得大于V了(变化后的速度不一定相同),于是科学家们决定研究这些特别的粒子。
科学家们对n个粒子做了特殊处理,为其从1到n分别编号,为了找出是哪些粒子的特性发生了变化(导致速度变化),他们准备让这些粒子依次通过一段相同长度的距离,速度越高的粒子通过这段距离所需的时间越短,由于技术问题,只能检测到粒子发射顺序和到达终点的顺序(没有两个粒子同时被发射或同时到达),请你通过这些数据计算出至少多少个例子特性发生了变化。(即速度大于通常情况)。
输入描述
第一行一个正整数n,表示粒子数星。
接下来一行包含n个正整数S1,S2.…Sn(1≤si≤n),为按发射顺序给出的粒子编号,S1-Sn为1-n的一个排列。
接下来一行包含n个正整数P1,P2,… Pn(1≤pi≤n),为按到达终点顺序给出的粒子编号,p1-pn为1-n的一个排列。
轮出描述
输出至少有多少个粒子特性发生了变化(即速度大于通常情况)
输入样例
5
5 4 3 2 1
1 5 3 4 2
输出样例
2
输出解释: 发射顺序是5 4 3 2 1,到达顺序是1 5 3 4 2。
可知1最晚发射,超过了前四个到达,1加速了。3在4之后发射的,但比4先到达了,所以3也加速了。
输出2。
思路
从上面的输出解释可以看出来1超过了前面4个,3超过了前面1个,其他的粒子没有超了0个。
可以联想到,这道题用逆序数来解决。
逆序数
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。也就是说,对于n个不同的元素,先规定各元素之间有一个标准次序(例如n个 不同的自然数,可规定从小到大为标准次序),于是在这n个元素的任一排列中,当某两个元素的实际先后次序与标准次序不同时,就说有1个逆序。一个排列中所有逆序总数叫做这个排列的逆序数。
举个例子:
5 4 2 3 1 —— 5的逆序数是4(比后面4个数都大),4的逆序数是3(比后面3个数大),2的逆序数是1,3的逆序数是1,1的逆序数是0
5 1 3 2 4 —— 5的逆序数是4(比后面4个数都大),1的逆序数是0,3的逆序数是1,2的逆序数是0,4的逆序数是0
解题过程
以输入样例来举例:
5
5 4 3 2 1
1 5 3 4 2
发射顺序:5 4 3 2 1
到达顺序:1 5 3 4 2
对应索引:4 0 2 1 3 【加上1后:5 1 3 2 4,实际含义是:粒子本应该是第x个到达的,但是如果他的逆序数大于0,则说明它超速了】
逆序数: 4 0 1 0 0
大于0的个数:2
以伪代码来描述:
发射顺序:list_a
到达顺序:list_b
对应索引:list_c
逆序数: list_d
ans: list_d中大于0的数
解题步骤:
- 接收参数list_a和list_b,list_c和list_d初始化为0
- 遍历list_b,找到每一个元素的对应索引,构成list_c
- 算出list_c的逆序数,构成list_d
- 计算list_d中大于0的数
代码
def getNum(num,lista):
return lista.index(num)
n = int(input())
list_a = list(map(int,input().split()))
list_b = list(map(int,input().split()))
list_c = [0 for i in range(n)]
list_d = [0 for i in range(n)]
index_c=0
for i in list_b:
list_c[index_c] = getNum(i,list_a)
index_c+=1
for i in range(n):
count = 0
for j in list_c[i+1:]:
if list_c[i] > j:
count += 1
list_d[i] = count
count = 0
for i in list_d:
if i > 0:
count += 1
print(count)
分析
时间复杂度O(N²),空间复杂度O(N)
结果
AC率为73%