我遇到了以下问题,
您将获得n个元素的数组A.现在,这些元素被添加到新列表L中,该列表最初为空,基于给定的q查询按特定顺序。
在将每个元素添加到列表L后,在所有组中打印最大组值。
我的方法是使用>[1]: sel.xpath("//div[@id='branchprofile']/script/text()")[0].extract()
<[1]: '\n(function(k,v){RMVH.ANALYTICS.DataLayer.pushKV(k,v);}(\'branch\',{"branchId":5112345,"companyName":"KLM","brandName":"London KLM",,"pageType":"Standard"})); '
,其中key是组号,value是包含组大小max的向量。小组我也有一个数组g和g [i]表示a [i]的组号,如果它不在任何组中,则为-1。下面的代码是我实现的一部分,但我确信有更好的方法可以解决这个问题,因为我的解决方案在某些情况下给了TLE和WA,我似乎无法弄清楚正确的方法。请提出解决此问题的最佳方法。
map<int,vector<int>>
。
答案 0 :(得分:0)
我实际上不会构建列表L.在找到新值时可能会花费太多代价:它本身是一个新组,它是否扩展了现有组,是否需要合并为两个组一?如果第一个值相距很远,那么您将拥有多个组,并且需要使用每个新的传入值进行迭代:这样效率不高。
我会先收集所有值,然后再看看它们是如何组合的。
有两种收集价值的方法:
将它们存储在列表中,并在收集完所有值后,按升序对列表进行排序
在大小为 n 的布尔数组中标记该条目。这样您就不必对它进行排序,但之后您需要迭代整个数组以按升序查找值。
当 q 远小于 n 时,方法1将是最佳的。方法2对于更大的 q 更好。
使用这两种方法,您将能够按升序迭代找到的值,同时这样做可以识别组,它们的值,并跟踪最大的组值。只需要一次扫描即可找到答案。
答案 1 :(得分:0)
让我们从两个简化的假设开始:
i
被“查询”,它将永远不会再被查询。(下面我将展示如何不需要这些假设,但现在这将简化图片。)
因此,每当我们“查询”索引i
时,就有四种情况:
i-1
目前是一个组的右端点(我的意思是它的最大索引),而i+1
当前是另一个组的左端点。
i
弥合它们之间的差距。i-1
目前是群组的右端点,但i+1
目前不在任何群组中。
i
。i-1
目前不在任何群组中,但i+1
目前是群组的左端点。
i
。i-1
和i+1
都不属于某个群组。
在所有情况下,需要注意的关键是我们只对组的端点感兴趣。因此,我们不需要从索引到其组的一般映射。 。 。这很好,因为当我们合并两个组时,那么从一个组更新每个索引以指向另一个组将是昂贵的。
所以我们只需要三个映射:
std::unordered_map<int, int> map_from_left_endpoint_to_right_endpoint;
std::unordered_map<int, int> map_from_right_endpoint_to_left_endpoint;
std::unordered_map<int, int> map_from_left_endpoint_to_largest_value;
为区分这四种情况,我们使用例如map_from_right_endpoint_to_left_endpoint.find(i - 1)
(返回指向i-1
是右端点的组的左端点的迭代器(如果适用);否则返回map_from_right_endpoint_to_left_endpoint.end()
)。然后,我们删除条目,因为它们变得不再适用(由于组在给定方向上被扩展或合并),此外(显然)插入新条目,并更新现有条目的值。
除了这些值,我们还需要一个
int maximum_group_value = 0;
每当我们扩展一个组或合并两个组时,我们检查结果组的值(意味着它的largest_value * (right_endpoint - left_endpoint + 1
)是否大于maximum_group_value
。如果是,我们更新maximum_group_value
并将其返回;如果没有,我们按原样返回maximum_group_value
。
现在,如果允许重复 ,那么在给定索引i
已经属于某个组之后可能会被“查询”该怎么办?
最简单的方法是简单地跟踪已查询的i
- s;但如果需要,更优雅的方法可能是将map_from_left_endpoint_to_right_endpoint
从std::unordered_map
更改为std::map
,然后使用以下内容:
bool is_already_in_a_group(
std::map<int, int> const & map_from_left_endpoint_to_right_endpoint,
int const i) {
// get iterator to first element *after* index (or to 'end()' if no such):
auto iter = map_from_left_endpoint_to_right_endpoint.upper_bound(index);
// if that pointer points to 'begin()', then there are no elements
// at or before index:
if (iter == map_from_left_endpoint_to_right_endpoint.begin()) {
return false;
}
// otherwise, move iterator to point to the last element whose key is
// less than or equal to index:
--iter;
// . . . and check whether the value of that element is greater than
// or equal to index (meaning that [key, value] spans index):
return iter->second >= index;
}
检查map_from_left_endpoint_to_right_endpoint
中小于或等于i
的最大键是否映射到大于或等于i
的值。
这为我们上面的案例分析添加了第五个案例 - “如果i
已经在一个组中,则不做任何事情并返回maximum_group_value
” - 但除此之外,没有任何效果。
请注意,如果我们愿意,同样的方法也可以让我们删除map_from_right_endpoint_to_left_endpoint
:通过将int get_left_endpoint_for_right_endpoint
语句更改为return
,可以轻松地将上述函数调整为return iter->second == index ? iter->first : -1;
此时,定义一个包含三个字段Group
,left_endpoint
和right_endpoint
)的largest_value
类变得明智,只需保留一个{{1} }}
最后 - 如果允许负值,那么“最大组值”实际上可以减少作为查询的结果怎么办? (例如,如果数组元素为map_from_left_endpoint_to_group
且查询为[-1, -10]
,i=0
,则结果为i=1
,maximum_group_value=-1
。)在此类中例如,我们需要跟踪所有当前组的值,因为它们中的任何一个都可能突然变为最大值。
为此,我们可以维护一堆按值排序的组,而不是存储单个maximum_group_value=-2
,我们在每次创建/扩展/合并组时都会进入这些组。 (我们可以使用int maximum_group_value
加上std::vector<Group>
加上适当的比较器,或者使用适当的std::push_heap
定义。)在每次查询之后,我们检查顶部组是否在heap(向量中的第一个元素)仍然是一个实际存在的组;如果是这样,我们返回它的值,否则我们弹出它(使用operator<(Group const &, Group const &)
)并重复。
作为优化,我们还存储std::pop_heap
,并在遇到非负数组元素时消除堆(因为只要给定的组包含非负数组-element,它的值永远不会再次减少,显然最大组值将是其中一个组的值。)