蓝桥杯-小朋友排队-python

简介: 蓝桥杯-小朋友排队-python

题目描述:


n 个小朋友站成一排。现在要把他们按身高从低到高的顺序排列,但是每次只能交换位置相邻的两个小朋友。每个小朋友都有一个不高兴的程度。开始的时候,所有小朋友的不高兴程度都是0。如果某个小朋友第一次被要求交换,则他的不高兴程度增加1,如果第二次要求他交换,则他的不高兴程度增加2(即不高兴程度为3),依次类推。当要求某个小朋友第k次交换时,他的不高兴程度增加k。

请问,要让所有小朋友按从低到高排队,他们的不高兴程度之和最小是多少。

如果有两个小朋友身高一样,则他们谁站在谁前面是没有关系的。

【数据格式】

   输入的第一行包含一个整数n,表示小朋友的个数。

   第二行包含 n 个整数 H1 H2 … Hn,分别表示每个小朋友的身高。

   输出一行,包含一个整数,表示小朋友的不高兴程度和的最小值。

例如,输入:

3

3 2 1

程序应该输出:

9


【样例说明】

  首先交换身高为3和2的小朋友,再交换身高为3和1的小朋友,再交换身高为2和1的小朋友,每个小朋友的不高兴程度都是3,总和为9。


【数据规模与约定】

   对于10%的数据, 1<=n<=10;

   对于30%的数据, 1<=n<=1000;

   对于50%的数据, 1<=n<=10000;

   对于100%的数据,1<=n<=100000,0<=Hi<=1000000。

资源约定:

峰值内存消耗 < 256M

CPU消耗  < 1000ms


思路


这里大佬的思路可以借鉴大佬思路

大佬是用c语言实现的,我们这里使用python实现。

根据题意,通过调整最终要得到一个从小到大的数组,其中一个小朋友被调整的次数为n,他的不高兴的程度为,所以我们只要知道每一位小朋友被调换的次数再全部加起来,就得到了我们最终的值

我们该怎么计算每个小朋友被调换的次数呢?这里我们用到了一种数据结构,树状数组。通过使用树状数组,可以很快的算出前缀和。通过前缀和,我们可以算出每个小朋友左边有多少人比他高,右边有多少人比他矮,两者相加,就是这个小朋友的n了。

我们这里用树状数组做两次逆序对,一次是正序处理,从左往右,找到右边矮的,一次是倒序处理,从右往左,找出左边高的。

关于逆序对的介绍可以参考这篇博客树状数组求逆序对


正序处理:

当前已经处理的数字个数减掉当前数字的前缀和即为以该数为较小数的逆序对个数。如图,比如当前已经读了n个数,而前缀和只有n-2个数,说明当前读到的数比之前读到的两个数要小,则找到了两个逆序对

k[i]=i-1-sum(H[i])

逆序处理:


用树状数组倒序处理数列,当前数字的前一个数的前缀和即为以该数为较大数的逆序对的个数。因为是从后往前读,当读到 i 时,发现它的前一个数的前缀和>0,则说明之前读过的数中有小于当前数的,我们将这个值加上前缀和即可


k[i]+=sum(H[i]-1)

代码


1. N=100000
2. 
3. def discretization(h):
4.     temp=list(set(h))
5.     temp.sort()
6. for i in range(len(h)):
7.         h[i]=temp.index(h[i])+1
8. 
9. def lowbit(x):
10. return x&-x
11. 
12. def update(x,d):
13.     while x<N:
14.         tree[x]+=d
15.         x+=lowbit(x)
16. 
17. def sum(x):
18.     s=0
19.     while x>0:
20.         s+=tree[x]
21.         x-=lowbit(x)
22. return s
23. 
24. n=int(input())
25. Hold=list(map(int,input().split()))
26. H=[0 for _ in range(N)]
27. for i in range(0,n):
28.     H[i+1]=Hold[i]+1
29. 
30. k=[0 for _ in range(N)]
31. 
32. #discretization(H)
33. tree=[0 for _ in range(N)]
34. for i in range(1,n+1):
35.     k[i]=i-1-sum(H[i])
36.     update(H[i],1)
37. 
38. tree=[0 for _ in range(N)]
39. for i in range(n,0,-1):
40.     k[i]+=sum(H[i]-1)
41.     update(H[i],1)
42. res=0
43. for i in range(1,n+1,1):
44.     res+=int((1+k[i])*k[i]/2)
45. print(res)


这个代码在蓝桥杯官网会超时,但在报名课程中可以通过,应该是系统问题

感谢罗老师的教程。

目录
相关文章
|
3月前
|
Python
蓝桥杯练习题(一):Python组之入门训练题
这篇文章是关于蓝桥杯Python组的入门训练题,包括Fibonacci数列、圆的面积、序列求和和A+B问题的具体代码实现和样例输出。
160 0
|
3月前
|
存储 机器学习/深度学习 算法
蓝桥杯练习题(三):Python组之算法训练提高综合五十题
蓝桥杯Python编程练习题的集合,涵盖了从基础到提高的多个算法题目及其解答。
136 3
蓝桥杯练习题(三):Python组之算法训练提高综合五十题
|
3月前
|
人工智能 Python
蓝桥杯练习题(四):Python组之历届试题三十题
关于蓝桥杯Python组历届试题的三十个练习题的总结,包括题目描述、输入输出格式、样例输入输出以及部分题目的解题思路和代码实现。
64 0
蓝桥杯练习题(四):Python组之历届试题三十题
|
3月前
|
存储 机器学习/深度学习 算法
蓝桥杯练习题(二):Python组之基础练习三十题
蓝桥杯Python编程练习题的集合,包含了三十个不同难度的编程题目,覆盖了基础语法、数据结构和算法等领域。
65 0
|
8月前
|
索引 Python 容器
【备战蓝桥杯】探索Python内置标准库collections的使用
【备战蓝桥杯】探索Python内置标准库collections的使用
106 1
|
8月前
|
开发者 Python
【备战蓝桥杯】如何使用Python 内置模块datetime去计算我与CSDN相遇的天数
【备战蓝桥杯】如何使用Python 内置模块datetime去计算我与CSDN相遇的天数
79 1
|
8月前
|
算法 测试技术 编译器
蓝桥杯-02-python组考点与14届真题
蓝桥杯-02-python组考点与14届真题
|
8月前
|
Python
第十三届蓝桥杯B组python(试题A:排列字母)
第十三届蓝桥杯B组python(试题A:排列字母)
72 0
|
8月前
|
人工智能 算法 测试技术
第十四届蓝桥杯第三期模拟赛 【python】(二)
第十四届蓝桥杯第三期模拟赛 【python】(二)
|
8月前
|
测试技术 Python
第十四届蓝桥杯第三期模拟赛 【python】(一)
第十四届蓝桥杯第三期模拟赛 【python】(一)