这题我也就看了好几个小时吧。终于!有点懂了!
上午看懂了用双指针写《下一个排序》后就在看这题。70分的代码很好写也很好想,就是模拟fx和gx,然后遍历一趟,得到最终的结果。
看了学霸的代码,debug了几个小时啊,终于感觉有点懂了,我真的是被自己蠢哭啊!
以第一个具体的例子说吧,首先用一个数组fx_count记录fx每段的元素个数。对于上述的例子,fx为[0,0,1,1,1,2,2,2,3,3],一共有四段,fx_count为[2,3,3,2]。
fx 0 0 1 1 1 2 2 2 3 3
gx 0 0 1 1 2 2 3 3 4 4
最外层的while循环,i表示当前第几段,又表示当前段每个f(x)的值。如i=0,表示第0段,0段的所有f(x)都为0。
fx_count[i]表示fx当前段还剩多少个值没有与gx的值进行比较。每个gx段一开始元素个数都是r,用gxnum表示gx的当前段还剩多少个值。
先进行判断,if fx_count[i] >= gxnum(如当i首次等于1时,fx_count[1]是3, gxnum是2)。那么最终要返回的结果ans,ans += gxnum *abs (i - value)。这里的i就是f(x)的值,value就是gx的值。计算了gxnum个数后,fx_count[i] -= gxnum(如fx_count[1]从3变成1)。 gx开启新段,所以这时候gxnum重新赋值为r且value值加一(gxnum=2,且value=2)。
否则,fx_count[i] < gxnum(如fx_count[1]是1, gxnum是2)。ans += fx_count[i] *abs (i - value)。
重点来了!
如果fx的当前段没比较的数目大于等于gx当前段没有比较的数目,那么ans加的是 gxnum abs (i - value) 。以上面例子中fx的 1 1 1和gx的1 1 2为例,此时fx_count[1]是3, gxnum是2,ans+= 2abs(1-1),ans为0。
而当fx的当前段没比较的数目小于gx当前段没有比较的数目,则ans加的是 fx_count[i] abs (i - value)。还是以上面例子中fx的 1 1 1和gx的1 1 2为例,此时fx_count[1]是3-2=1, ans+= 1abs(1-2),ans为1。
总而言之,ans在进行累加的时候,abs(i-value)前面的系数以fx和gx当前段没进行比较的元素个数中的较小值为准。
上代码上代码:
n, N = map(int, input().split())
A = list(map(int, input().split()))
r = N // (n+1)
A.insert(0, 0)
# fx_count数组记录的是f每一段的长度
fx_count = [0]*(n+1)
for i in range(n):
fx_count[i] = A[i+1] - A[i]
fx_count[n] = N-A[-1]
# 表示fx的第i段 且该段的每个fx的值都为i
i = 0
# value表示gx的当前值
value = 0
# gxnum 初始值记录的是 r
gxnum = r
ans = 0
while i <= n:
if fx_count[i] >= gxnum:
ans += gxnum * abs(i-value)
# fx_count[i] fx当前段中还剩下多少个
fx_count[i] -= gxnum
# 此时gx要开启新的下一段
# 所以value+1 gxnum重新变成了r
value += 1
gxnum = r
else:
ans += fx_count[i] * abs(i-value)
# 当前gx的同一段中还剩多少个元素
gxnum -= fx_count[i]
i += 1
print(ans)