我的输入由一些比赛中的排名组成(比如马拉松比赛),其值在[0, N)
范围内。有几个子竞赛(例如,基于年龄,性别等)仅对子集team
感兴趣并且另一个子集not_eligible
不符合条件。
我正在寻找一种有效的算法(最好用标准库编写),它将更新排名。例如:
auto team = std::vector<int>{ 1, 2, 9, 13 };
auto not_eligible = std::vector<int>{ 8, 10, 12 };
std::vector<int> result;
// some algorithm
assert(result == std::vector<int>{ 1, 2, 8, 10 });
因为只有1个#9(即#8)以下的同一者没有资格,所以#9的等级减少1,因为有3个不合格的终结者(即#8,#10和#12)在#13之前,对于该特定子竞赛,该等级从#13更新为#10到#10。
注意 8和10是result
的一部分,但不是因为它们是从non_eligible
合并的,而是因为它们的排名是从{{1 }}
如何使用标准算法的组合实现上述目标?我希望能够以team
复杂度为O(N + M)
和N
的输入范围(例如,通过5条腿M
)进行此操作。
更新:我也对逆算法感兴趣:给定子竞赛的排名,如何在添加以前不符合条件的参与者时更新次级竞争中的竞争者的等级?
答案 0 :(得分:1)
没有一种明显的方法可以利用现有的algorithm
;你最好采用merge
的示例代码并进行调整:
template<class InputIt1, class InputIt2, class OutputIt>
OutputIt update_ranks(InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first)
{
typename std::iterator_traits<InputIt1>::value_type adjust = {};
while (first1 != last1) {
if (first2 != last2 && *first2 < *first1) {
++adjust;
++first2;
} else {
*d_first = *first1 - adjust;
++first1;
++d_first;
}
}
return d_first;
}
对于反向,再次调整merge
应该有效。
答案 1 :(得分:1)
我设法找到一个围绕3脚版std::transform
的简单包装器,原始问题和反问题(输入序列中的两个算法都是O(N + M)
)
template<class InputIt1, class InputIt2, class OutputIt>
OutputIt remove_ranks(InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first)
{
auto delta = 0;
return std::transform(first1, last1, d_first,
[&, first2](int rank) mutable {
while (first2 != last2 && rank > *first2) { ++first2; ++delta; }
return rank - delta;
});
}
template<class InputIt1, class InputIt2, class OutputIt>
OutputIt insert_ranks(InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first)
{
auto delta = 0;
return std::transform(first1, last1, d_first,
[&, first2](int rank) mutable {
while (first2 != last2 && rank + delta >= *first2) { ++first2; ++delta; }
return rank + delta;
});
}