📜  在段树中不使用延迟传播和点查询的范围更新

📅  最后修改于: 2021-09-06 06:40:29             🧑  作者: Mango

给定一个由N 0 个组成的数组arr[]和一个由以下两种类型的查询组成的二维数组Q[][]

  • 1 LRX:[L, R]范围内的所有元素增加X
  • 2 X:在数组的X索引处打印元素。

方法:思路是利用 Segment Tree 的概念来执行类型2 的查询,使用差异数组来执行类型1 的查询。请按照以下步骤解决问题:

  • 对于{ 1, L, R, X }类型的查询,使用 Segment 树更新arr[L] += Xarr[R + 1] -= X。
  • 对于{2, X}类型的查询,使用 Segment Tree 查找[0, X]范围内数组元素的总和并打印获得的总和。

下面是上述方法的实现:

C++
// C++ program to implement
// the above approach
#include 
using namespace std;
 
// Function to update the array elements
// at idx pos, i.e arr[pos] += X
void update(int Tree[], int idx, int s,
            int e, int pos, int X)
{
    // If current node is a
    // leaf nodes
    if (s == e) {
 
        // Update Tree[idx]
        Tree[idx] += X;
    }
 
    else {
 
        // Divide segment tree into left
        // and right subtree
        int m = (s + e) / 2;
 
        // Check if pos lies in left subtree
        if (pos <= m) {
 
            // Seach pos in left subtree
            update(Tree, 2 * idx, s, m, pos, X);
        }
        else {
 
            // Search pos in right subtree
            update(Tree, 2 * idx + 1, m + 1, e,
                   pos, X);
        }
 
        // Update Tree[idx]
        Tree[idx]
            = Tree[2 * idx] + Tree[2 * idx + 1];
    }
}
 
// Function to find the sum from
// elements in the range [0, X]
int sum(int Tree[], int idx, int s,
        int e, int ql, int qr)
{
    // Check if range[ql, qr] equals
    // to range [s, e]
    if (ql == s && qr == e)
        return Tree[idx];
 
    if (ql > qr)
        return 0;
 
    // Divide segment tree into
    // left substree and
    // right substree
    int m = (s + e) / 2;
 
    // Return sum of elements in the range[ql, qr]
    return sum(Tree, 2 * idx, s, m, ql, min(m, qr))
           + sum(Tree, 2 * idx + 1, m + 1, e,
                 max(ql, m + 1), qr);
}
 
// Function to find Xth element
// in the array
void getElement(int Tree[], int X, int N)
{
    // Print element at index x
    cout << "Element at " << X << " is "
         << sum(Tree, 1, 0, N - 1, 0, X) << endl;
}
 
// Function to update array elements
// in the range [L, R]
void range_Update(int Tree[], int L,
                  int R, int X, int N)
{
 
    // Update arr[l] += X
    update(Tree, 1, 0, N - 1, L, X);
 
    // Update arr[R + 1] += X
    if (R + 1 < N)
        update(Tree, 1, 0, N - 1, R + 1, -X);
}
 
// Drivers Code
int main()
{
    // Size of array
    int N = 5;
 
    int Tree[4 * N + 5] = { 0 };
 
    int arr[] = { 0, 0 };
    vector >
        Q = { { 1, 0, 1, 100 }, { 2, 1 } };
 
    int cntQuery = Q.size();
    for (int i = 0; i < cntQuery; i++) {
 
        if (Q[i][0] == 1) {
 
            range_Update(Tree, Q[i][1],
                         Q[i][2], Q[i][3], N);
        }
        else {
 
            getElement(Tree, Q[i][1], N);
        }
    }
}


Java
// Java program to implement
// the above approach
import java.util.*;
class GFG
{
 
// Function to update the array elements
// at idx pos, i.e arr[pos] += X
static void update(int Tree[], int idx, int s,
            int e, int pos, int X)
{
   
    // If current node is a
    // leaf nodes
    if (s == e)
    {
 
        // Update Tree[idx]
        Tree[idx] += X;
    }
 
    else
    {
 
        // Divide segment tree into left
        // and right subtree
        int m = (s + e) / 2;
 
        // Check if pos lies in left subtree
        if (pos <= m)
        {
 
            // Seach pos in left subtree
            update(Tree, 2 * idx, s, m, pos, X);
        }
        else
        {
 
            // Search pos in right subtree
            update(Tree, 2 * idx + 1, m + 1, e,
                   pos, X);
        }
 
        // Update Tree[idx]
        Tree[idx]
            = Tree[2 * idx] + Tree[2 * idx + 1];
    }
}
 
// Function to find the sum from
// elements in the range [0, X]
static int sum(int Tree[], int idx, int s,
        int e, int ql, int qr)
{
   
    // Check if range[ql, qr] equals
    // to range [s, e]
    if (ql == s && qr == e)
        return Tree[idx];
 
    if (ql > qr)
        return 0;
 
    // Divide segment tree into
    // left substree and
    // right substree
    int m = (s + e) / 2;
 
    // Return sum of elements in the range[ql, qr]
    return sum(Tree, 2 * idx, s, m, ql, Math.min(m, qr))
           + sum(Tree, 2 * idx + 1, m + 1, e,
                 Math.max(ql, m + 1), qr);
}
 
// Function to find Xth element
// in the array
static void getElement(int Tree[], int X, int N)
{
   
    // Print element at index x
    System.out.print("Element at " +  X+ " is "
         + sum(Tree, 1, 0, N - 1, 0, X) +"\n");
}
 
// Function to update array elements
// in the range [L, R]
static void range_Update(int Tree[], int L,
                  int R, int X, int N)
{
 
    // Update arr[l] += X
    update(Tree, 1, 0, N - 1, L, X);
 
    // Update arr[R + 1] += X
    if (R + 1 < N)
        update(Tree, 1, 0, N - 1, R + 1, -X);
}
 
// Drivers Code
public static void main(String[] args)
{
   
    // Size of array
    int N = 5;
    int Tree[] = new int[4 * N + 5];
    int arr[] = { 0, 0 };
    int[][]
        Q = { { 1, 0, 1, 100 }, { 2, 1 } };
    int cntQuery = Q.length;
    for (int i = 0; i < cntQuery; i++)
    {
        if (Q[i][0] == 1)
        {
            range_Update(Tree, Q[i][1],
                         Q[i][2], Q[i][3], N);
        }
        else
        {
            getElement(Tree, Q[i][1], N);
        }
    }
}
}
 
// This code is contributed by shikhasingrajput


Python3
# Python3 program to implement
# the above approach
 
# Function to update the array elements
# at idx pos, i.e arr[pos] += X
def update(Tree, idx, s, e, pos, X):
   
    # If current node is a
    # leaf nodes
    if (s == e):
 
        # Update Tree[idx]
        Tree[idx] += X
 
    else:
 
        # Divide segment tree into left
        # and right subtree
        m = (s + e) // 2
 
        # Check if pos lies in left subtree
        if (pos <= m):
 
            # Seach pos in left subtree
            update(Tree, 2 * idx, s, m, pos, X)
        else:
 
            # Search pos in right subtree
            update(Tree, 2 * idx + 1, m + 1, e,pos, X)
 
        # Update Tree[idx]
        Tree[idx] = Tree[2 * idx] + Tree[2 * idx + 1]
 
# Function to find the sum from
# elements in the range [0, X]
def sum(Tree, idx, s, e, ql, qr):
   
    # Check if range[ql, qr] equals
    # to range [s, e]
    if (ql == s and qr == e):
        return Tree[idx]
 
    if (ql > qr):
        return 0
 
    # Divide segment tree into
    # left substree and
    # right substree
    m = (s + e) // 2
 
    # Return sum of elements in the range[ql, qr]
    return sum(Tree, 2 * idx, s, m, ql, min(m, qr))+ sum(Tree, 2 * idx + 1, m + 1, e,max(ql, m + 1), qr)
 
# Function to find Xth element
# in the array
def getElement(Tree, X, N):
   
    # Prelement at index x
    print("Element at", X, "is ", sum(Tree, 1, 0, N - 1, 0, X))
 
# Function to update array elements
# in the range [L, R]
def range_Update(Tree, L, R, X, N):
 
    # Update arr[l] += X
    update(Tree, 1, 0, N - 1, L, X)
 
    # Update arr[R + 1] += X
    if (R + 1 < N):
        update(Tree, 1, 0, N - 1, R + 1, -X)
 
# Drivers Code
if __name__ == '__main__':
   
    # Size of array
    N = 5
    Tree = [0]*(4 * N + 5)
    arr = [0, 0]
    Q = [ [1, 0, 1, 100], [2, 1] ]
    cntQuery = len(Q)
    for i in range(cntQuery):
        if (Q[i][0] == 1):
            range_Update(Tree, Q[i][1], Q[i][2], Q[i][3], N)
        else:
            getElement(Tree, Q[i][1], N)
 
# This code is contributed by mohit kumar 29.


C#
// C# program to implement
// the above approach
using System;
public class GFG
{
 
  // Function to update the array elements
  // at idx pos, i.e arr[pos] += X
  static void update(int []Tree, int idx, int s,
                     int e, int pos, int X)
  {
 
    // If current node is a
    // leaf nodes
    if (s == e)
    {
 
      // Update Tree[idx]
      Tree[idx] += X;
    }
 
    else
    {
 
      // Divide segment tree into left
      // and right subtree
      int m = (s + e) / 2;
 
      // Check if pos lies in left subtree
      if (pos <= m)
      {
 
        // Seach pos in left subtree
        update(Tree, 2 * idx, s, m, pos, X);
      }
      else
      {
 
        // Search pos in right subtree
        update(Tree, 2 * idx + 1, m + 1, e,
               pos, X);
      }
 
      // Update Tree[idx]
      Tree[idx]
        = Tree[2 * idx] + Tree[2 * idx + 1];
    }
  }
 
  // Function to find the sum from
  // elements in the range [0, X]
  static int sum(int []Tree, int idx, int s,
                 int e, int ql, int qr)
  {
 
    // Check if range[ql, qr] equals
    // to range [s, e]
    if (ql == s && qr == e)
      return Tree[idx];
 
    if (ql > qr)
      return 0;
 
    // Divide segment tree into
    // left substree and
    // right substree
    int m = (s + e) / 2;
 
    // Return sum of elements in the range[ql, qr]
    return sum(Tree, 2 * idx, s, m, ql, Math.Min(m, qr))
      + sum(Tree, 2 * idx + 1, m + 1, e,
            Math.Max(ql, m + 1), qr);
  }
 
  // Function to find Xth element
  // in the array
  static void getElement(int []Tree, int X, int N)
  {
 
    // Print element at index x
    Console.Write("Element at " +  X+ " is "
                  + sum(Tree, 1, 0, N - 1, 0, X) +"\n");
  }
 
  // Function to update array elements
  // in the range [L, R]
  static void range_Update(int []Tree, int L,
                           int R, int X, int N)
  {
 
    // Update arr[l] += X
    update(Tree, 1, 0, N - 1, L, X);
 
    // Update arr[R + 1] += X
    if (R + 1 < N)
      update(Tree, 1, 0, N - 1, R + 1, -X);
  }
 
  // Drivers Code
  public static void Main(String[] args)
  {
 
    // Size of array
    int N = 5;
    int []Tree = new int[4 * N + 5];
    int []arr = { 0, 0 };
    int[,]Q = { { 1, 0, 1, 100 }, { 2, 1, 0, 0 } };
    int cntQuery = Q.GetLength(0);
    for (int i = 0; i < cntQuery; i++)
    {
      if (Q[i, 0] == 1)
      {
        range_Update(Tree, Q[i, 1],
                     Q[i, 2], Q[i, 3], N);
      }
      else
      {
        getElement(Tree, Q[i, 1], N);
      }
    }
  }
}
 
// This code is contributed by 29AjayKumar


Javascript


输出:
Element at 1 is 100

时间复杂度: O(|Q| * log(N))
辅助空间: O(N)

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live