如何解决对两个排列中的对a,b进行计数,以使两个中的indexa<indexb
给出(1,2,3,.. N)的两个排列,
Consider for n = 5
5 4 3 2 1
3 2 4 1 5
查找对(a,b)的对数,以便两个排列中的index(a)
(4,1) index(4)<index(1) in both permutations.
(3,1)
(2,1)
(3,2)
我们可以轻松地在O(n 2 )中执行此操作,但我觉得我们可以在O(nlogn)中执行此操作。你能帮忙吗?
另一个例子...
for n = 5
3 4 1 5 2
1 3 2 5 4
这里的答案是5
(3,4) index(3)<index(4) in both perms.
(3,5) index(3)<index(5) in both perms.
(3,2)
(1,5)
(1,2)
解决方法
是的,这可以在O( n log n )时间内以非常优雅的方式解决。由于数字本身并不重要(只是它们的索引),因此请重新标记它们,以使第一个排列变得微不足道;这需要O( n )时间。在示例中,重新标记为1 → 3
,2 → 5
,3 → 1
,4 → 2
,5 → 4
。
3 4 1 5 2 → 1 2 3 4 5
1 3 2 5 4 → 3 1 5 4 2
现在且仅当a n 选择2)减去inversions的数量,可以用O( n log n ) 时间;参见例如this other Stack Overflow Q&A。
,可以用order statistics rb tree解决。
我们将这两个数组称为 a 和 b 。(它们可以互换)
使其长度为 n 。
我们需要 b 的反置换 p 。 (即: p [x] 包含 b 中数字 x 的索引)
设置 s 为带有订单统计信息的集合。
我们将已存储的 b 元素的索引存储在 s 中。
我们从 i = 0 迭代到 n-1 (让数组索引为零):
b 中编号为 a [i] 之后的元素数为 C = n-1-p [a [i]] 。
其中,我们需要那些尚未出现在 a 中的元素。可以使用 s 计算得出。我们知道 s 的大小,在log(n)中,我们可以计算 p [a [i]] 在 s 中的位置。从 C 中减去 s 中 p [a [i]] 之后的元素数,并将其添加到答案中。
在每次迭代结束时,我们将 p [a [i]] 添加到 s 。
编辑:如果将c ++与gcc编译器一起使用,则已经实现了这样的集合,并且used在竞争性编程中也是如此。
,我将按照以下方式进行操作。让我们使用您给出的示例:
3 4 1 5 2
1 3 2 5 4
保留一个结构,该结构可以(1)添加一个数字,(2)给定一个数字,可以报告该结构中有多少个数字更大(例如,给定2,如果该结构包含1、3和... 4,它将返回2)。
现在在第一个排列A
中从右向左迭代。对于每个数字,A[i]
在迭代的第一个数字之后,通过在第二个置换中插入该数字的索引来标记先前访问的数字A[i+1]
。然后查询结构中有多少元素大于A[i]
中B
的索引。
回到我们的示例:
indexes 0 1 2 3 4
A 3 4 1 5 2
B 1 3 2 5 4
Iteration right to left on A:
2 skip
5 insert index of 2 in B
structure: { 2 }
query structure for how many are
greater than index of 5 in B
> 3: 0
result: 0
1 insert 3 in structure
structure: { 2,3 }
query > 0: 2
result: 2
4 insert 0 in structure
structure: { 0,2,3}
query > 4: 0
result: 2
3 insert 4 in structure
structure: { 0,3,4 }
query > 1: 3
result: 2 + 3 = 5
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。