如何快速将数字添加到向量中的一系列元素

时间:2018-07-08 07:00:49

标签: c++ performance vector stl

如何在向量中将常数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;
             }
       }

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

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

2 个答案:

答案 0 :(得分:2)

据我所知,您有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的一些教程:

答案 1 :(得分:1)

您有/期望多少个重叠间隔?

如果范围很大,则很有可能它们会重叠。对于所有这些重叠,您需要计算多次。想象以下情况:

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

您可以解决重叠问题,这样每个元素只能有一个加法(当然,在进行任何计算之前,您需要先查询范围 ,然后将其存储在适当的数据结构中):< / p>

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

由于现在具有独立的范围,因此您还可以并行化添加的内容(例如,将范围放入队列中,并让每个线程在完成前一个范围后立即从中取一个-需要保护队列免受竞争条件的侵害)