序列算法-前缀和与差分

序列算法-前缀和

一般的前缀和是对于数组的求和,即对数组的某一子数组进行求和,即Sum(i,j) == sum[i] - sum[j-1]

不仅如此前缀和还能用于任何含可逆运算的运算符包括异或xor

上述的子数组和的问题属于数组固定,大量访问的问题优化。

下面给出一个大量做区间加的情况:

给定一个序列a 有很多次操作,每个操作形如:A l r k 将a_[l,r]每个值加上k. 最后输出整个数组。复杂度要求O(n).

如果用传统方法,n次操作当lr区间长度达到n就成了O(n^2)了,自然不符合题意。

所以这里利用到了差分数组(描述序列元素的递推关系,以更快的方式体现序列元素的增减)。

对于如下序列:

5 4 7 2 4 3 1

经过如下计算:

得到差分数组:

5 -1 3 -5 2 -1 -2

然后再求差分数组的前缀和可以发现:

sum[i] == line[i]

并且给差分数组的一个元素+x后,其后面直到-x的元素(不包括),他们的前缀和均+i(即line元素+i),这就回归到了我们的题目要求上。

由查分数组的这些性质可以解决更多类似这种问题。

所以代码如下:

int n;//数组元素个数
int l,r,k;
int a[100005];
int change[100005];
int sum[100005];

void fun(int m)//m次操作
{
    
    
    memset(change,0,sizeof(change));
    memset(sum,0,sizeof(sum));
    for(int i = 1;i <= n;i++)       //求差
    {
    
    
        cin >> a[i];
        change[i] += a[i] - a[i-1];
    }
    for(int i = 0;i < m;i++)        //对差分元素进行加减运算
    {
    
    
        cin>>l>>r>>k;
        change[l] += k;
        change[r + 1] -= k;
    }
    for(int i = 1;i <= n;i++)       //求差分数组前缀和并输出
    {
    
    
        sum[i] = sum[i-1] + change[i];
        cout<<sum[i]<<" ";
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_46052886/article/details/113459926
今日推荐