给出n个在圆形轨道上奔跑的跑步者。每个跑步者穿过另一个跑步者时,都会交换宝石。给定每个跑步者完成循环轨迹所花费的时间(以分钟为单位)的数组和整数k。我们需要找到在经过k分钟之前进行的交换次数。
[编辑1]:我考虑过使用所有数字的hcf作为交汇点,但是无法通过。任何帮助都很好。
答案 0 :(得分:1)
我对这类问题的回答通常是先自己尝试一下,但这是一个非常困难的问题,所以我将为您提供解决方案。
我们在这里要做的是计算一个跑步者超越另一个跑步者的次数。首先,我们可以根据跑步者的速度对他们进行排序,这将在以后派上用场。对于第i
名跑步者,我们可以轻松地计算出他们将跑的圈数,我将其称为L(i)
。对于i
比j
快的两个跑步者i
和j
,i
通过j
的次数是{{1} }。我们的解决方案是所有floor(L(i) - L(j))
和i
对,其中j
的所有值的总和。
如果i > j
的限制足够小,则可以遍历所有这些对,并在n
时间内求和。但是,如果O(n^2)
大,则速度太慢。如果我们只想计算所有n
的{{1}}的总和而没有下限函数,则可以使用前缀总和在线性时间内完成。
如果我们的跑步者按照速度顺序从0到L(i) - L(j)
进行编号,则对于i > j
的每个值,对于n - 1
的所有值,i
的总和小于L(i) - L(j)
等于j
,其中i
是L(i) * i - P(i - 1))
之和的预先计算的值。现在我们需要处理下限功能。对于两个实数P(j)
和L(0) + L(1) + L(2) + ... + L(j)
,其中x
,如果y
的小数部分大于或等于x > y
,则floor(x - y)
等于floor(x) - floor(y)
到x
的小数部分,否则到y
。
因此,如果我们需要计算一个跑步者floor(x) - floor(y) - 1
通过另一个跑步者的次数,我们可以先使用上述前缀和技术对每个i
的底值进行计算,然后再计算减去L
的小数部分大于j
的小数部分的L(j)
值的数量。在实数上找到L(i)
的小数部分大于j
的小数部分的L(j)
的数量基本上是对实数的inversion counting,这可以通过二进制索引来完成树。
最终的复杂度为L(i)
。