arrays - 计算 k 分钟后将发生的交换次数的程序

标签 arrays algorithm

给定 n 名运行者在圆形跑道上运行。每个运行者穿过另一个运行者时,他们交换 gem 。给定每个运行者完成圆形跑道所用时间(以分钟为单位)的数组和一个整数 k。我们需要找到在过去 k 分钟之前将发生的交换次数。

[编辑 1]:我想过使用所有数字的 hcf 作为会面点,但无法通过。任何帮助都会很好。

最佳答案

我们在这里要做的是计算一个运行者超过另一个运行者的次数。首先,我们可以按速度对运行者进行排序,这稍后会派上用场。对于第 i 名运行者,我们可以很容易地计算出他们要跑的圈数,我将其称为 L(i)。对于两个运行者 ij,其中 ij 快,i< 的次数 将通过 jfloor(L(i) - L(j))。我们的解决方案是所有 ij 对的这个值的总和,其中 i > j

如果 n 的限制足够小,您可以遍历所有这些对并在 O(n^2) 时间内对值求和。但是如果 n 很大,这会太慢。如果我们只是想计算所有 i > jL(i) - L(j) 的总和而不使用 floor 函数,我们可以在线性时间内完成此操作使用前缀和。

如果我们的运行者按照速度顺序从 0 到 n - 1 编号,对于 i 的每个值,L(i ) - L(j) 对于小于 ij 的所有值等于 L(i) * i - P(i - 1 )),其中 P(j)L(0) + L(1) + L(2) + ... + L 之和的预计算值(j)。现在我们需要处理 floor 函数。对于两个实数 xy,其中 x > yfloor(x - y) 等于 floor(x) - floor(y) 如果 x 的小数部分大于或等于 y 的小数部分,并且 floor(x) - floor(y) - 1 否则。

因此,如果我们需要计算一个运行者 i 超过另一个运行者的次数,我们可以首先使用上面描述的前缀和技术计算值,每个 L 值,然后减去 j 值的个数,其中 L(j) 的小数部分大于 L(i)< 的小数部分。查找 L(j) 的小数部分大于 L(i) 的小数部分的 j 值的个数基本上是 inversion counting实数,这可以用二叉索引树来完成。

最终的复杂度是O(n log n)

关于arrays - 计算 k 分钟后将发生的交换次数的程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51637451/

相关文章:

c# - 如何正确初始化和填充多维数组?

Java - 如何在属于对象数组的对象内查找变量的值?

javascript - 将句子字符串拆分为单词数组,然后将单词数组拆分为单词数组中的字符数组

python - 如何使用 CUDA 或 OpenCL 加速 block 匹配算法?

javascript - 当没有键时如何访问嵌套的 json 值?

ios - Swift - 就地更新对象

javascript - 使用 Javascript 或 Ruby 对大小进行分类的算法

java - Java中数组元素的高效交换

algorithm - Dart 实现失败的 Perlin 噪音

c++ - 如何找出两个整数的乘积中设置了多少位(等于 1)