差异数组 | O(1)中的范围更新查询

原文: https://www.geeksforgeeks.org/difference-array-range-update-query-o1/

考虑一个由整数组成的数组A[]并遵循以下两种类型的查询。

  1. update(l, r, x):将x加到从A[l]A[r]的所有值中(包括两端)。

  2. printArray():打印当前修改后的数组。

示例

Input : A [] { 10, 5, 20, 40 }
        update(0, 1, 10)
        printArray()
        update(1, 3, 20)
        update(2, 2, 30)
        printArray()
Output : 20 15 20 40
         20 35 70 60
Explanation : The query update(0, 1, 10) 
adds 10 to A[0] and A[1]. After update,
A[] becomes {20, 15, 20, 40}       
Query update(1, 3, 20) adds 20 to A[1],
A[2] and A[3]. After update, A[] becomes
{20, 35, 40, 60}.
Query update(2, 2, 30) adds 30 to A[2]. 
After update, A[] becomes {20, 35, 70, 60}.

一个简单解决方案要执行以下操作:

  1. update(l, r, x):从lr运行循环,并将x添加到从A[l]A[r]的所有元素中。

  2. printArray():仅打印A[]

以上两个操作的时间复杂度为O(n)

有效解决方案是使用差分数组。

给定数组A[i]的差数组D[i]定义为D[i] = A[i] - A[i-1](对于0 < i < N)和D[0] = A[0],考虑基于 0 的索引。 差值数组可用于执行范围更新查询l r x,其中l是左索引,r是右索引,x是要添加的值,在所有查询之后,您都可以从中返回原始数组。 可以以O(1)复杂度执行更新范围操作的地方。

  1. update(l, r, x):将x添加到D[l]并将其从D[r + 1]中减去,即我们做D[l] += xD[r + 1] -= x

  2. printArray():执行A[0] = D[0]并打印。 对于其余元素,执行A[i] = A[i-1] + D[i]并打印它们。

这里更新的时间复杂度提高到O(1)。 请注意,printArray()仍需要O(n)时间。

C++

// C++ code to demonstrate Difference Array 
#include <bits/stdc++.h> 
using namespace std; 

// Creates a diff array D[] for A[] and returns 
// it after filling initial values. 
vector<int> initializeDiffArray(vector<int>& A) 
{ 
    int n = A.size(); 

    // We use one extra space because 
    // update(l, r, x) updates D[r+1] 
    vector<int> D(n + 1); 

    D[0] = A[0], D[n] = 0; 
    for (int i = 1; i < n; i++) 
        D[i] = A[i] - A[i - 1]; 
    return D; 
} 

// Does range update 
void update(vector<int>& D, int l, int r, int x) 
{ 
    D[l] += x; 
    D[r + 1] -= x; 
} 

// Prints updated Array 
int printArray(vector<int>& A, vector<int>& D) 
{ 
    for (int i = 0; i < A.size(); i++) { 
        if (i == 0) 
            A[i] = D[i]; 

        // Note that A[0] or D[0] decides 
        // values of rest of the elements. 
        else
            A[i] = D[i] + A[i - 1]; 

        cout << A[i] << " "; 
    } 
    cout << endl; 
} 

// Driver Code 
int main() 
{ 
    // Array to be updated 
    vector<int> A{ 10, 5, 20, 40 }; 

    // Create and fill difference Array 
    vector<int> D = initializeDiffArray(A); 

    // After below update(l, r, x), the 
    // elements should become 20, 15, 20, 40 
    update(D, 0, 1, 10); 
    printArray(A, D); 

    // After below updates, the 
    // array should become 30, 35, 70, 60 
    update(D, 1, 3, 20); 
    update(D, 2, 2, 30); 
    printArray(A, D); 

    return 0; 
} 

Java

// Java code to demonstrate Difference Array 
class GFG { 
      
    // Creates a diff array D[] for A[] and returns 
    // it after filling initial values. 
    static void initializeDiffArray(int A[], int D[]) 
    { 
          
        int n = A.length; 
  
        D[0] = A[0]; 
        D[n] = 0; 
        for (int i = 1; i < n; i++) 
            D[i] = A[i] - A[i - 1]; 
    } 
  
    // Does range update 
    static void update(int D[], int l, int r, int x) 
    { 
        D[l] += x; 
        D[r + 1] -= x; 
    } 
  
    // Prints updated Array 
    static int printArray(int A[], int D[]) 
    { 
        for (int i = 0; i < A.length; i++) { 
              
            if (i == 0) 
                A[i] = D[i]; 
  
            // Note that A[0] or D[0] decides 
            // values of rest of the elements. 
            else
                A[i] = D[i] + A[i - 1]; 
  
            System.out.print(A[i] + " "); 
        } 
          
        System.out.println(); 
          
        return 0; 
    } 
      
    // Driver Code 
    public static void main(String[] args) 
    { 
        // Array to be updated 
        int A[] = { 10, 5, 20, 40 }; 
        int n = A.length; 
        // Create and fill difference Array 
        // We use one extra space because 
        // update(l, r, x) updates D[r+1] 
        int D[] = new int[n + 1]; 
        initializeDiffArray(A, D); 
  
        // After below update(l, r, x), the 
        // elements should become 20, 15, 20, 40 
        update(D, 0, 1, 10); 
        printArray(A, D); 
  
        // After below updates, the 
        // array should become 30, 35, 70, 60 
        update(D, 1, 3, 20); 
        update(D, 2, 2, 30); 
          
        printArray(A, D); 
    } 
} 
  
// This code is contributed by Anant Agarwal.

Python3

# Python3 code to demonstrate Difference Array 
  
# Creates a diff array D[] for A[] and returns 
# it after filling initial values. 
def initializeDiffArray( A): 
    n = len(A) 
  
    # We use one extra space because 
    # update(l, r, x) updates D[r+1] 
    D = [0 for i in range(0 , n + 1)] 
  
    D[0] = A[0]; D[n] = 0
      
    for i in range(1, n ): 
        D[i] = A[i] - A[i - 1] 
    return D 
  
  
# Does range update 
def update(D, l, r, x): 
  
    D[l] += x 
    D[r + 1] -= x 
  
  
# Prints updated Array 
def printArray(A, D): 
  
    for i in range(0 , len(A)): 
        if (i == 0): 
            A[i] = D[i] 
  
        # Note that A[0] or D[0] decides 
        # values of rest of the elements. 
        else: 
            A[i] = D[i] + A[i - 1] 
  
        print(A[i], end = " ") 
      
    print ("") 
  
  
# Driver Code 
A = [ 10, 5, 20, 40 ] 
  
# Create and fill difference Array 
D = initializeDiffArray(A) 
  
# After below update(l, r, x), the 
# elements should become 20, 15, 20, 40 
update(D, 0, 1, 10) 
printArray(A, D) 
  
# After below updates, the 
# array should become 30, 35, 70, 60 
update(D, 1, 3, 20) 
update(D, 2, 2, 30) 
printArray(A, D) 
  
# This code is contributed by Gitanjali.

C

// C# code to demonstrate Difference Array 
using System; 
  
class GFG { 
      
    // Creates a diff array D[] for A[] and returns 
    // it after filling initial values. 
    static void initializeDiffArray(int []A, int []D) 
    { 
          
        int n = A.Length; 
  
        D[0] = A[0]; 
        D[n] = 0; 
        for (int i = 1; i < n; i++) 
            D[i] = A[i] - A[i - 1]; 
    } 
  
    // Does range update 
    static void update(int []D, int l, int r, int x) 
    { 
        D[l] += x; 
        D[r + 1] -= x; 
    } 
  
    // Prints updated Array 
    static int printArray(int []A, int []D) 
    { 
        for (int i = 0; i < A.Length; i++) { 
              
            if (i == 0) 
                A[i] = D[i]; 
  
            // Note that A[0] or D[0] decides 
            // values of rest of the elements. 
            else
                A[i] = D[i] + A[i - 1]; 
  
            Console.Write(A[i] + " "); 
        } 
          
        Console.WriteLine(); 
          
        return 0; 
    } 
      
    // Driver Code 
    public static void Main() 
    { 
        // Array to be updated 
        int []A = { 10, 5, 20, 40 }; 
        int n = A.Length; 
        // Create and fill difference Array 
        // We use one extra space because 
        // update(l, r, x) updates D[r+1] 
        int []D = new int[n + 1]; 
        initializeDiffArray(A, D); 
  
        // After below update(l, r, x), the 
        // elements should become 20, 15, 20, 40 
        update(D, 0, 1, 10); 
        printArray(A, D); 
  
        // After below updates, the 
        // array should become 30, 35, 70, 60 
        update(D, 1, 3, 20); 
        update(D, 2, 2, 30); 
          
        printArray(A, D); 
    } 
} 
  
// This code is contributed by vt_m.

输出:

20 15 20 40 
20 35 70 60