O(n) 取得数组中每个元素右边最后一个比它大的元素

题目

2019.9.7,icpc徐州网络赛的E题 XKC's basketball team ,计蒜客上还可以做。

链接:https://nanti.jisuanke.com/t/41387

Input

The first line contains two integers n and m ( 2 ≤ n ≤ 5∗10^5 ,0 ≤ m ≤ 10^9) .

The following  line contain n integers W1​..Wn​(0 ≤ Wi​ ≤ 10^9) .

Output

A row of n integers separated by spaces , representing the anger of every member .

样例输入

6 13 4 5 6 2 10

样例输出

4 3 2 1 0 -1

 

题意:

对于数组中的每个元素来说,如果它加上m之后,右边仍然有比它大的数(有多个的话,取距离最远的),这个距离就是我们要的结果,不存在取 -1。所以问题就是,取得数组中每个元素右边最后一个比它大的元素。

思路:

看了 “O(n) 取得数组中每个元素右边第一个比它大的元素” 的思路想到的。

  • 建立一个Node (value, index);value是原数组的值 + m,index是对应的索引。(具体的value是什么,视问题而定)
  • 建立壹 Node 的 value 值升序的优先级队列。也就是小根堆。
  •  i = n - 1,开始向前遍历

不断用当前堆顶的value值与arr[i]进行比较,如果堆顶元素小于arr[i],则找到需要找的元素。因为堆顶是最小的元素,如果堆顶大于arr[i],则i--,继续重复当前步骤。

  • 直到遍历完成,堆中大概率还会剩下几个(加+m之后,原数组中没有元素比它们大了),这些元素对应的 res 都是 -1 。
 1 #include <iostream>
 2 #include <queue>
 3 #include <stdio.h>
 4 using namespace std;
 5  
 6 int arr[500005];
 7 int anger[500005];
 8  
 9 struct Node {
10     int value, index;
11     Node(int v, int i) :value(v), index(i) {};
12     bool operator< (const Node& n)const {
13         return n.value < value;
14     }
15 };
16 priority_queue <Node>pq;
17  
18 int main() {
19     int n, m;
20     cin >> n >> m;
21     for (int i = 0; i < n; i++) {
22         scanf("%d", &arr[i]);
23         anger[i] = -1;
24         pq.push(Node(arr[i] + m, i));
25     }
26  
27     for (int i = n - 1; i >= 0; i--) {
28         while (!pq.empty()) {
29             int top = pq.top().value;
30             if (arr[i] >= top) {
31                 int index = pq.top().index;
32                 pq.pop();
33                 if (i > index) {
34                     anger[index] = i - index - 1;
35                 }
36                 else anger[index] = -1;
37             }
38             else break;
39         }
40     }
41  
42     for (int i = 0; i < n; i++) {
43         printf("%d", anger[i]);
44         if (i != n - 1)printf(" ");
45     }
46     
47     return 0;
48 }

 

转载于:https://www.cnblogs.com/czc1999/p/11487024.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 如果您想要比较多个数组并获取n个不重复的组合,您可以使用Python中的itertools模块来实现。以下是一个样例代码,可以帮助您理解如何使用itertools模块: ```python import itertools # 假设您有3个数组 a = [1, 2, 3] b = [4, 5] c = [6, 7] # 将这些数组组合成一个列表 arrays = [a, b, c] # 计算所有可能的组合,并添加到一个集合中以去除重复项 combinations = set(itertools.product(*arrays)) # 取前n个不重复的组合 n = 5 unique_combinations = list(itertools.islice(combinations, n)) print(unique_combinations) ``` 在上面的代码中,我们首先将所有要比较的数组组合成一个列表。然后,我们使用`itertools.product()`函计算所有可能的组合,并使用`set()`函将它们添加到一个集合中以去除重复项。最后,我们使用`itertools.islice()`函从这个集合中取出前n个不重复的组合。 请注意,如果您要比较的数组非常大,那么计算所有可能的组合可能会非常耗时和占用内存。在这种情况下,您可能需要考虑使用更级的算法来查找n个不重复的组合。 ### 回答2: 要实现多个数组的对比,取得n个不重复组合,可以通过以下步骤进行: 1. 首先,确定需要对比的多个数组。将这些数组分别存储起来,每个数组可以用一个列表来表示。 2. 然后,利用嵌套循环来遍历这些数组。假设有m个数组,则需要嵌套m层循环来遍历每个数组元素。 3. 在循环中,选择一个数组元素作为基准,依次与其他数组元素进行比较。可以使用条件语句来判断是否有重复。 4. 如果发现有重复的元素,则跳过当前循环,继续下一个元素的比较。 5. 如果没有重复的元素,将这些元素组合起来形成一个组合,并将该组合存储到一个结果列表中。 6. 继续循环,直到找到n个不重复组合。 7. 最后返回结果列表即可。 需要注意的是,在实现时,可以根据具体需求来确定如何处理重复元素。有时候可能需要保留所有组合,有时候可能需要仅保留其中一种组合。此外,时间复杂度也需要考虑,如果数组过大或组合量较多,可能需要采用更效的算法来优化程序性能。 ### 回答3: 假设有m个数组,每个数组中有n个元素。现在我们要通过对比这些数组取得n个不重复的组合方式。 首先,我们需要确定组合的量。根据计算组合量的公式,如果有m个数组,每个数组中有n个元素,那么不重复组合的量为C(m, n),即从m个数组中选择n个数组进行组合。 接下来,我们可以使用嵌套循环的方式来遍历这些数组。外层循环遍历第一个数组元素,内层循环遍历第二个数组元素。以此类推,直到遍历完所有的数组。 在每一次循环中,我们可以将当前选中的元素保存在一个临时的数组中。当这个临时数组的长度达到了n个元素,即我们已经取得一个完整的组合。这时,我们可以将这个组合保存在一个结果数组中。 在进行嵌套循环时,需要注意避免选择相同的数组和重复的元素。我们可以设置一个变量来记录已经使用过的数组元素,确保下一次的选择不会重复。 最后,当所有的组合都找到之后,我们可以将结果数组返回,即得到了这m个数组对比取得n个不重复组合的结果。 需要注意的是,这个方法的时间复杂度是O(m^n),在m和n较大时,可能会有较的计算成本。因此,在实际应用中,我们可能需要根据具体情况进行优化或使用其他算法来解决此问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值