题目
思路
这个题是跟这一年的第一题是相互关联的,第一题“序列查询”给出了分块计算的思想,这个题就延续下来继续来用了
要是按题目那么求f,遍历求解的话会超时,观察样例给出的f和g的数据,可以发现f和g的值都是按区间一段一段的,那么就是看怎么求出这个区间的长度
但是f和g的分段不是同步的,有交叉,那么就要先按一个区间走(比如说先按f的区间分),然后再在这个基础上看有没有g的区间的端点
找到f和g的一致区间后分段求解
这里可以发现,f的值可以从原数组直接看出,g每个段的长度是一样的,这样可以不用求f和g的数组,只需要求分段的长度就可以了
代码
70分
这是按题干给的求f的公式求的,需要遍历的话就会超时
import math
n,N = map(int,input().split())
A =[0] + list(map(int,input().split())) # 递增
fx = [0]*N
for x in range(N):
tmp_index = (n+1)//N*x
while tmp_index <=n and A[tmp_index]<=x:
tmp_index += 1
if tmp_index == n and A[tmp_index]<=x:
fx[x] = tmp_index
else:
fx[x] = tmp_index-1
r = N//(n+1)
error = 0
g = [0]*N
for i in range(N):
g[i] = i//r
error += math.fabs(g[i]-fx[i])
print(int(error))
100分
借鉴第一题分段求的思想,关键是怎么去分段
n,N = map(int,input().split())
A =[0] + list(map(int,input().split()))+[N] # 递增
r = N//(n+1)
Long = 0
sum = 0
def g(x):
return x//r
for i in range(1,n+2):
sum1 = 0
j = A[i-1]
while j<A[i]:
gx = g(j)
numEnd = (gx+1)*r-1
if numEnd>A[i]-1: # f和g有交叉
numEnd = A[i]-1
numLong = numEnd-j+1
f_g = abs(i-1-gx)
sum1 += f_g*numLong
Long = numLong
j+=Long
sum+=sum1
print(sum)