【问题标题】:how to add a number to a range of elements in vector very fast如何快速将数字添加到向量中的一系列元素
【发布时间】:2018-12-16 04:42:12
【问题描述】:

如何将常量k 添加到向量中的一系列元素[a,b],非常快! 我编写的代码适用于q 查询数量相对较短的输入:

    long int a,b,k,n;
    vector<long int> v(n+1,0);
    for( long int i=0; i<q ;i++)
       {
          cin>>a>>b>>k;
          for(int j=a-1; j<=b-1; j++)
             {
               v[j]+=k;
             }
       }

但这显然是一个非常缓慢的解决方案!对于较大的 krange 值,代码需要更长的时间 例如 [a,b]=6581237, 9872072k=87106 将花费相对较长的计算时间。 那么有没有更快的方法可以在更短的时间内完成工作?

编辑:我的方法为大量查询(10^7)和范围达到 10^7 的数量级时提供超时。

【问题讨论】:

  • 通过[]vector 添加325 万个元素不会花费几十年的时间。几秒钟,也许。不知道你遇到了什么问题。
  • n 在您使用之前似乎没有被初始化。我建议使用minimal reproducible example 更新问题。
  • 除了@user4581301 的评论,请说明您正在计时的代码部分以及如何您正在执行该计时。
  • Adding a value to a vector for millions of elements does not take decades。该示例是在没有优化的情况下编译的。大约一秒钟后输出“完成”消息。我认为您是过早优化的受害者。
  • 在我看来是个 XY 问题。你原来的问题是什么?

标签: c++ performance vector stl


【解决方案1】:

据我所知,您有Q 查询,对于每个查询,您需要为数组范围内的每个元素添加一个数字。这就解释了为什么您认为对具有几百万个元素的向量执行此操作会花费太长时间,因为执行一次所需的时间不到一秒。

您需要的是Fenwick tree,或带有延迟传播的segment tree,它允许您更新一系列元素或以对数时间查询元素的值。段树还可以在对数时间内执行范围查询。

Fenwick 树本身可以执行点更新和前缀和查询,但我们可以使用以下方法使其执行范围更新和点查询:

//Add val to every element in [left, right]:
update(left, val);
update(right + 1, -val);

//Query the value at index x:
query(x);

对于分段树解决方案,您将需要lazy propagation 来执行范围更新。

我认为如果您是第一次学习 Wikipedia 页面,可能会有些困惑,所以这里有一些来自 hackerearth.com 的教程:

【讨论】:

    【解决方案2】:

    您有/预计有多少重叠间隔?

    如果范围非常大,那么它们确实重叠的可能性很大。对于所有这些重叠,您需要多次计算加法。想象以下情况:

    [10; 100] + 20 [30; 50] - 10 [40; 120] + 10

    您可以解决重叠问题,使每个元素只有一个添加项(当然,您需要在进行任何计算之前查询范围,然后将它们存储在一些适当的数据结构中): [ 10; 30] + 20 [ 30; 40] + 10 [ 40; 50] + 20 [ 50; 100] + 30 [100; 120] + 10

    由于现在有独立的范围,您可以额外并行化添加(例如,通过将范围放入队列中,并让每个线程在完成前一个范围后立即获取一个 - 需要保护队列免受竞争条件的影响) .

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-02
      • 1970-01-01
      • 2010-11-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多