📜  给定三元组上可能减少的最大对数(1)

📅  最后修改于: 2023-12-03 15:27:34.467000             🧑  作者: Mango

给定三元组上可能减少的最大对数

在一个三元组 $(a_i, b_i, c_i)$ 中,满足 $a_i \leq a_{i+1}$,$b_i \leq b_{i+1}$,$c_i \leq c_{i+1}$,定义为有序三元组。

现在有一个长度为 $n$ 的序列 $(a_i, b_i, c_i)$,请你找出在它上面至少能删去多少个元素,使得剩下的序列中的所有三元组都是有序的。

要求实现一个函数,输入参数为长度为 $n$ 的序列 $(a_i, b_i, c_i)$,输出为可能减少的最大对数。

解法

根据题目,我们要找到一个最长的有序三元组子序列,并删除其他元素。

我们可以先将三元组按照 $a_i$ 升序排序,再按照 $b_i$ 升序和 $c_i$ 升序排序。然后,我们将得到一个按照顺序排列的三元组 $(a_{i_1}, b_{i_1}, c_{i_1}), (a_{i_2}, b_{i_2}, c_{i_2}), \dots, (a_{i_n}, b_{i_n}, c_{i_n})$。

现在,我们要找到一个最长的下降子序列并删除剩余元素。可以用二分查找来找到最长的下降子序列。以按 $b_i$ 升序排序的元素为例:

我们定义一个序列 $dp$,其中 $dp[i]$ 存储了长度为 $i$ 的下降子序列的末尾元素的最小值。

假设当前已经处理了前 $k$ 个元素,现在来处理第 $k+1$ 个元素 $b_{i_{k+1}}$。如果 $b_{i_{k+1}}$ 大于 $dp$ 中的最后一个元素,则将其添加到 $dp$ 的末尾;否则,在 $dp$ 中二分查找第一个比 $b_{i_{k+1}}$ 小的元素,并将其替换为 $b_{i_{k+1}}$。最终,$dp$ 的长度就是最长的下降子序列的长度。

这个方法的时间复杂度为 $O(n \log n)$。

以下是代码片段:

def max_dec_pairs(arr):
    arr.sort(key=lambda x: (x[0], x[1], x[2]))
    n = len(arr)

    dp_b = []
    for i in range(n):
        idx = bisect_left(dp_b, arr[i][1])
        if idx == len(dp_b):
            dp_b.append(arr[i][1])
        else:
            dp_b[idx] = arr[i][1]

    dp_c = []
    for i in range(n):
        idx = bisect_left(dp_c, arr[i][2])
        if idx == len(dp_c):
            dp_c.append(arr[i][2])
        else:
            dp_c[idx] = arr[i][2]

    return n - max(len(dp_b), len(dp_c))

其中,arr 为输入的三元组序列,函数返回可能减少的最大对数。

总结

本题的解法和最长下降子序列的解法类似,主要是要对三元组按照顺序排序并找到最长下降子序列。具体实现可以用二分查找来找到最长下降子序列。时间复杂度为 $O(n \log n)$,空间复杂度为 $O(n)$。