【问题标题】:How do you solve the given scenario with given memory constraints?你如何解决给定内存限制的给定场景?
【发布时间】:2016-12-11 09:48:11
【问题描述】:

一排有N个花园,编号从1到N,每个第i个花园都有Ci胡萝卜。 我们必须将总胡萝卜的值存储在数组的每个可能的连续子序列的花园中。

现在我们必须对获得的数组进行排序并回答以下 Q 查询。在每个查询中,我们都想知道上面获得的排序数组中从 L 到 R(包括两者)的值的总和。

示例测试用例

Input:
3 3    //First number is the total no. of gardens. Second is no. of queries
4 9 1  //No. of carrots in each of the gardens
1 6    // Query return sum from L to R.
2 4
3 3

Output:
51 23 9  // Respective Output for 3 queries.

说明

Gardens [1, 2, 3] has [4, 9, 1] carrots respectively.
All possible continuous gardens are { [1], [2], [3], [1, 2], [2, 3], [1, 2, 3] } .

Sum of carrots in each subgardens is {4, 9, 1, 13, 10, 14} 
Sorted array is {1, 4, 9, 10, 13, 14} .

Now Queries for 1 6 sum is 1+4+9+10+13+14 which is 51,
next 2 4 so 4+9+10 hence 23, and 3 3 which is 9.

现在我已经使用模拟/后缀总和解决了这个问题,但原来的问题有很大的约束

1 ≤ No. of gardens ≤ 2*10^5
1 ≤ Carrots in a particular garden ≤ 100
1 ≤ Li ≤ Ri ≤ N(N+1)/2
1 ≤ No. of queries ≤ 20

现在,当我尝试为大到 2*10^5 的 N 创建所有可能的连续子序列时。我得到的连续子序列约为 10^10,太大而无法存储在数组中。

对此有什么可能的解决方法,如何在不实际存储所有连续子序列的总和的情况下回答查询?

【问题讨论】:

  • 查询次数有什么限制?
  • 为查询添加约束

标签: algorithm sorting binary-search


【解决方案1】:

这个怎么样?

假设c[] = {c_1,c_2,..,c_n},给定数组。和p[] = {c1, c1+c2,..,c1+...+cn} 前缀数组。直观地将c 的所有连续子分成n 组(每个组都是非递减数组):

  1. { c1, c1+c2, .. , }
  2. { c2, c2+c3, .. , c2+...+cn} ...

    n. { cn }

请注意,使用前缀数组可以在恒定时间内计算所有上述元素。

让我们找到值x,这样在我们选择的组中恰好有l 元素小于x。 (x 的最大值为c0+c1+..+cn)。为此,我们在x 上运行二进制搜索,并为给定的x 计算l 的值,我们在每个选定的组中运行二进制搜索。所以我们将在每个组中的元素数量少于x,我们需要总结一下。此操作的复杂度为n*log(x)*log(x)

现在我们得到范围[l, r]。假设恰好有l-1 元素小于xlr 元素小于xr。所以剩下的就是计算每组中小于xr的元素之和,然后减去每组中小于xl的相应总和。使用二进制搜索和前缀总和数组可以直接计算。

编辑

这里是使用上述方法的解决方案:https://ideone.com/2JTw0X

如果有任何问题,请询问。至于这种情况如何处理,如果确定范围的值不存在,我们就需要计算偏移量,很简单。例如1, 1, 1, 1, 1。构建的组是:

{1,2,3,4,5}, {1,2,3,4},...,{1}。所以如果我们想找到值x,s.t.恰好三个数字小于x,我们找到最小值x',s.t。 f(x') >= 3。在这种情况下x'=1f(1)=5 且严格大于3,因此我们将3(offset) 添加到答案中,并计算每组中小于x'-1 = 0 的所有元素之和,即为零。

【讨论】:

  • 我们怎样才能找到 x 的值,这样对于像 1,1,1,1,1 这样的输入正好有 l 个元素现在对于查询 (2,3) 没有 x其中恰好有 l 个更少的元素,它们或多或少,因为许多子序列的总和为 1。
  • 添加了对您的问题的回答和完整的 C++ 解决方案。干杯:)
猜你喜欢
  • 2017-07-01
  • 1970-01-01
  • 2017-12-29
  • 1970-01-01
  • 2013-07-09
  • 1970-01-01
  • 1970-01-01
  • 2017-01-15
  • 2017-08-19
相关资源
最近更新 更多