假设我们得到一个长度为A[]
的数组N
,我们必须回答Q
个查询,其中包含两个整数L,R
。我们必须找到A[L]
到A[R]
的数字,其频率至少为(R-L+1)/2
。如果不存在这样的号码,那么我们必须打印“没有这样的号码”
我只能考虑O(Q*(R-L))
运行频率计数器的方法,并首先从L to R
获取数组中最常用的数字。然后计算它的频率。
但需要进行更多优化。
约束: 1<= N <= 3*10^5
,, 1<=Q<=10^5
,1<=L<=R<=N
答案 0 :(得分:2)
我知道O((N + Q) * sqrt(N))
解决方案:
如果在阵列中发生至少B
次,请拨打一个号码。数组中最多有N / B
个重数。
如果查询段是&#34;短&#34; (R - L + 1 < 2 * B
),我们可以在O(B)
时间内回答它(通过简单地遍历范围的所有元素)。
如果查询段是&#34; long&#34; (R - L + 1 >= 2 * B
),频繁的元素必须很重。我们可以迭代所有重数,然后检查是否至少有一个匹配(为此,我们可以预先计算每个重元素的出现次数的前缀和,并在[L, R]
段中找到它出现的次数时间)。
如果我们为某个常量B = C * sqrt(N)
设置C
,则此解决方案将在O((N + Q) * sqrt(N))
时间运行并使用O(N * sqrt(N))
内存。正确选择C
,可能符合时间和内存限制。
还有一个在O(N + Q * log N * k)
时间内运行的随机解决方案。
让我们为数组中的每个唯一元素存储一个出现位置的向量。现在我们可以在O(log N)
时间内找到固定范围内固定元素的出现次数(对出现的向量进行两次二进制搜索)。
对于每个查询,我们都会执行以下操作:
O(log N)
时间内检查其出现次数1 / 2
。如果我们执行k
次,则找不到它的概率为(1 / 2) ^ k
正确选择k
(以便每个查询的O(k * log N)
足够快且(1 / 2) ^ k
相当小),此解决方案应该通过。
两种解决方案都易于编码(第一种只需要前缀和,第二种只使用出现的向量和二进制搜索)。如果我必须对它们进行编码,我会选择后者(前者可能会更加痛苦地挤压时间和内存限制)。