📌  相关文章
📜  通过在给定范围内交替排列数组元素的符号来计算总和的查询

📅  最后修改于: 2021-04-24 15:08:30             🧑  作者: Mango

给定大小为N的数组arr []和2D数组Q [] [] ,该数组由以下两种类型的查询组成:

  • 1 X Val:更新arr [X] = Val
  • 2 LR:找到在[L,R]范围内具有交替符号的数组元素的总和。

例子:

方法:可以使用段树解决问题。这个想法是遍历数组并检查数组元素的索引是否为负,然后将数组元素乘以-1 。请按照以下步骤解决问题:

  • 使用变量i遍历数组arr []并检查索引i是否为奇数。如果发现为真,则更新arr [i] = -Val
  • 对于类型1,X,Val的查询,请检查X是否为偶数。如果发现为真,则使用段树更新arr [X] = Val
  • 否则,使用段树更新arr [X] = -Val
  • 对于类型2 LR:的查询,请检查L是否为偶数。如果发现为真,则使用段树打印范围为[L,R]的数组元素之和。
  • 否则,使用段树在[L,R]范围内找到数组元素的总和,然后将获得的总和乘以-1进行打印。

下面是上述方法的实现:

C++
// C++  program to implement
// the above approach
 
#include 
using namespace std;
 
// Function to build the segment tree
void build(int tree[], int arr[], int start,
           int end, int index)
{
 
    // If current node is a leaf node
    // of the segment tree
    if (start == end) {
 
        if (start % 2 == 0) {
 
            // Update tree[index]
            tree[index] = arr[start];
        }
 
        else {
 
            // Update tree[index]
            tree[index] = -arr[start];
        }
        return;
    }
 
    // Divide the segment tree
    int mid = start + (end - start) / 2;
 
    // Update on L segment tree
    build(tree, arr, start, mid,
          2 * index + 1);
 
    // Update on R segment tree
    build(tree, arr, mid + 1, end,
          2 * index + 2);
 
    // Find the sum from L subtree
    // and R subtree
    tree[index] = tree[2 * index + 1] + tree[2 * index + 2];
}
 
// Function to update elements at index pos
// by val in the segment tree
void update(int tree[], int index, int start,
            int end, int pos, int val)
{
 
    // If current node is a leaf node
    if (start == end) {
 
        // If current index is even
        if (start % 2 == 0) {
 
            // Update tree[index]
            tree[index] = val;
        }
 
        else {
 
            // Update tree[index]
            tree[index] = -val;
        }
        return;
    }
 
    // Divide the segment tree elements
    // into L and R subtree
    int mid = start + (end - start) / 2;
 
    // If element lies in L subtree
    if (mid >= pos) {
 
        update(tree, 2 * index + 1, start,
               mid, pos, val);
    }
    else {
        update(tree, 2 * index + 2, mid + 1,
               end, pos, val);
    }
 
    // Update tree[index]
    tree[index]
        = tree[2 * index + 1] + tree[2 * index + 2];
}
 
// Function to find the sum of array elements
// in the range [L, R]
int FindSum(int tree[], int start, int end,
            int L, int R, int index)
{
 
    // If start and end not lies in
    // the range [L, R]
    if (L > end || R < start) {
        return 0;
    }
 
    // If start and end comleately lies
    // in the range [L, R]
    if (L <= start && R >= end) {
 
        return tree[index];
    }
    int mid = start + (end - start) / 2;
 
    // Stores sum from left subtree
    int X = FindSum(tree, start, mid, L,
                    R, 2 * index + 1);
 
    // Stores sum from right subtree
    int Y = FindSum(tree, mid + 1, end, L,
                    R, 2 * index + 2);
 
    return X + Y;
}
 
int main()
{
 
    int arr[] = { 1, 2, 3, 4 };
    int N = sizeof(arr) / sizeof(arr[0]);
    int tree[4 * N + 5] = { 0 };
    build(tree, arr, 0, N - 1, 0);
 
    int Q[][3] = { { 2, 0, 3 }, { 1, 1, 5 }, { 2, 1, 2 } };
 
    int cntQuey = 3;
    for (int i = 0; i < cntQuey; i++) {
 
        if (Q[i][0] == 1) {
 
            update(tree, 0, 0, N - 1,
                   Q[i][1], Q[i][2]);
        }
 
        else {
 
            if (Q[i][1] % 2 == 0) {
 
                cout << FindSum(tree, 0, N - 1,
                                Q[i][1], Q[i][2], 0)
                     << " ";
            }
            else {
 
                cout << -FindSum(tree, 0, N - 1,
                                 Q[i][1], Q[i][2], 0)
                     << " ";
            }
        }
    }
}


Java
// Java program to implement
// the above approach
import java.util.*;
  
class GFG{
  
// Function to build the segment tree
static void build(int tree[], int arr[], int start,
           int end, int index)
{
 
    // If current node is a leaf node
    // of the segment tree
    if (start == end) {
 
        if (start % 2 == 0) {
 
            // Update tree[index]
            tree[index] = arr[start];
        }
 
        else {
 
            // Update tree[index]
            tree[index] = -arr[start];
        }
        return;
    }
 
    // Divide the segment tree
    int mid = start + (end - start) / 2;
 
    // Update on L segment tree
    build(tree, arr, start, mid,
          2 * index + 1);
 
    // Update on R segment tree
    build(tree, arr, mid + 1, end,
          2 * index + 2);
 
    // Find the sum from L subtree
    // and R subtree
    tree[index] = tree[2 * index + 1] + tree[2 * index + 2];
}
 
// Function to update elements at index pos
// by val in the segment tree
static void update(int tree[], int index, int start,
            int end, int pos, int val)
{
 
    // If current node is a leaf node
    if (start == end) {
 
        // If current index is even
        if (start % 2 == 0) {
 
            // Update tree[index]
            tree[index] = val;
        }
 
        else {
 
            // Update tree[index]
            tree[index] = -val;
        }
        return;
    }
 
    // Divide the segment tree elements
    // into L and R subtree
    int mid = start + (end - start) / 2;
 
    // If element lies in L subtree
    if (mid >= pos)
    {
        update(tree, 2 * index + 1, start,
               mid, pos, val);
    }
    else
    {
        update(tree, 2 * index + 2, mid + 1,
               end, pos, val);
    }
 
    // Update tree[index]
    tree[index]
        = tree[2 * index + 1] + tree[2 * index + 2];
}
 
// Function to find the sum of array elements
// in the range [L, R]
static int FindSum(int tree[], int start, int end,
            int L, int R, int index)
{
 
    // If start and end not lies in
    // the range [L, R]
    if (L > end || R < start)
    {
        return 0;
    }
 
    // If start and end comleately lies
    // in the range [L, R]
    if (L <= start && R >= end)
    {
        return tree[index];
    }
    int mid = start + (end - start) / 2;
 
    // Stores sum from left subtree
    int X = FindSum(tree, start, mid, L,
                    R, 2 * index + 1);
 
    // Stores sum from right subtree
    int Y = FindSum(tree, mid + 1, end, L,
                    R, 2 * index + 2);
    return X + Y;
}
  
// Driver Code
public static void main(String[] args)
{
    int arr[] = { 1, 2, 3, 4 };
    int N = arr.length;
    int tree[] = new int[4 * N + 5];
    Arrays.fill(tree, 0);
    build(tree, arr, 0, N - 1, 0);
    int Q[][] = { { 2, 0, 3 }, { 1, 1, 5 }, { 2, 1, 2 } };
    int cntQuey = 3;
    for (int i = 0; i < cntQuey; i++)
    {
        if (Q[i][0] == 1)
        {
            update(tree, 0, 0, N - 1,
                   Q[i][1], Q[i][2]);
        }
        else {
            if (Q[i][1] % 2 == 0)
            {
                System.out.print(FindSum(tree, 0, N - 1,
                                Q[i][1], Q[i][2], 0) + " ");
            }
            else
            {
                System.out.print(-FindSum(tree, 0, N - 1,
                                 Q[i][1], Q[i][2], 0)+ " ");
            }
        }
    }
}
}
 
// This code is contributed by code_hunt.


Python3
# Python3  program to implement
# the above approach
 
# Function to build the segment tree
def build(tree, arr, start, end, index):
 
    # If current node is a leaf node
    # of the segment tree
    if (start == end):
        if (start % 2 == 0):
 
            # Update tree[index]
            tree[index] = arr[start]
        else:
 
            # Update tree[index]
            tree[index] = -arr[start]
        return
 
    # Divide the segment tree
    mid = start + (end - start) // 2
 
    # Update on L segment tree
    build(tree, arr, start, mid, 2 * index + 1)
 
    # Update on R segment tree
    build(tree, arr, mid + 1, end, 2 * index + 2)
 
    # Find the sum from L subtree
    # and R subtree
    tree[index] = tree[2 * index + 1] + tree[2 * index + 2]
 
# Function to update elements at index pos
# by val in the segment tree
def update(tree, index, start, end, pos, val):
 
    # If current node is a leaf node
    if (start == end):
 
        # If current index is even
        if (start % 2 == 0):
 
            # Update tree[index]
            tree[index] = val
        else:
 
            # Update tree[index]
            tree[index] = -val
        return
 
    # Divide the segment tree elements
    # into L and R subtree
    mid = start + (end - start) // 2
 
    # If element lies in L subtree
    if (mid >= pos):
        update(tree, 2 * index + 1, start, mid, pos, val)
    else:
        update(tree, 2 * index + 2, mid + 1, end, pos, val)
 
    # Update tree[index]
    tree[index] = tree[2 * index + 1] + tree[2 * index + 2]
 
# Function to find the sum of array elements
# in the range [L, R]
def FindSum(tree, start, end, L, R, index):
 
    # If start and end not lies in
    # the range [L, R]
    if (L > end or R < start):
        return 0
 
    #If start and end comleately lies
    #in the range [L, R]
    if (L <= start and R >= end):
        return tree[index]
    mid = start + (end - start) // 2
 
    # Stores sum from left subtree
    X = FindSum(tree, start, mid, L, R, 2 * index + 1)
 
    # Stores sum from right subtree
    Y = FindSum(tree, mid + 1, end, L, R, 2 * index + 2)
 
    return X + Y
 
  # Driver code
if __name__ == '__main__':
 
    arr = [1, 2, 3, 4]
    N = len(arr)
    tree = [0 for i in range(4 * N + 5)]
    build(tree, arr, 0, N - 1, 0)
    Q = [ [ 2, 0, 3 ], [ 1, 1, 5 ], [ 2, 1, 2 ] ]
    cntQuey = 3
    for i in range(cntQuey):
        if (Q[i][0] == 1):
            update(tree, 0, 0, N - 1, Q[i][1], Q[i][2])
        else:
            if (Q[i][1] % 2 == 0):
                print(FindSum(tree, 0, N - 1, Q[i][1], Q[i][2], 0),end=" ")
            else:
                print(-FindSum(tree, 0, N - 1, Q[i][1], Q[i][2], 0),end=" ")
                 
# This code is contributed by mohit kumar 29


C#
// C#  program to implement
// the above approach
using System;
class GFG
{
     
    // Function to build the segment tree
    static void build(int[] tree, int[] arr, int start,
               int end, int index)
    {
      
        // If current node is a leaf node
        // of the segment tree
        if (start == end)
        {  
            if (start % 2 == 0)
            {
      
                // Update tree[index]
                tree[index] = arr[start];
            }
      
            else
            {
      
                // Update tree[index]
                tree[index] = -arr[start];
            }
            return;
        }
      
        // Divide the segment tree
        int mid = start + (end - start) / 2;
      
        // Update on L segment tree
        build(tree, arr, start, mid,
              2 * index + 1);
      
        // Update on R segment tree
        build(tree, arr, mid + 1, end,
              2 * index + 2);
      
        // Find the sum from L subtree
        // and R subtree
        tree[index] = tree[2 * index + 1] + tree[2 * index + 2];
    }
      
    // Function to update elements at index pos
    // by val in the segment tree
    static void update(int[] tree, int index, int start,
                int end, int pos, int val)
    {
      
        // If current node is a leaf node
        if (start == end)
        {
      
            // If current index is even
            if (start % 2 == 0)
            {
      
                // Update tree[index]
                tree[index] = val;
            }
      
            else
            {
      
                // Update tree[index]
                tree[index] = -val;
            }
            return;
        }
      
        // Divide the segment tree elements
        // into L and R subtree
        int mid = start + (end - start) / 2;
      
        // If element lies in L subtree
        if (mid >= pos)
        {
      
            update(tree, 2 * index + 1, start,
                   mid, pos, val);
        }
        else
        {
            update(tree, 2 * index + 2, mid + 1,
                   end, pos, val);
        }
      
        // Update tree[index]
        tree[index]
            = tree[2 * index + 1] + tree[2 * index + 2];
    }
      
    // Function to find the sum of array elements
    // in the range [L, R]
    static int FindSum(int[] tree, int start, int end,
                int L, int R, int index)
    {
      
        // If start and end not lies in
        // the range [L, R]
        if (L > end || R < start)
        {
            return 0;
        }
      
        // If start and end comleately lies
        // in the range [L, R]
        if (L <= start && R >= end)
        {
      
            return tree[index];
        }
        int mid = start + (end - start) / 2;
      
        // Stores sum from left subtree
        int X = FindSum(tree, start, mid, L,
                        R, 2 * index + 1);
      
        // Stores sum from right subtree
        int Y = FindSum(tree, mid + 1, end, L,
                        R, 2 * index + 2);
      
        return X + Y;
    }
 
  // Driver code
  static void Main()
  {
    int[] arr = { 1, 2, 3, 4 };
    int N = arr.Length;
    int[] tree = new int[4 * N + 5];
    build(tree, arr, 0, N - 1, 0);
  
    int[,] Q = { { 2, 0, 3 }, { 1, 1, 5 }, { 2, 1, 2 } };
  
    int cntQuey = 3;
    for (int i = 0; i < cntQuey; i++)
    {
        if (Q[i, 0] == 1)
        {
            update(tree, 0, 0, N - 1,
                   Q[i, 1], Q[i, 2]);
        }
  
        else
        {
            if (Q[i, 1] % 2 == 0)
            {
                Console.Write(FindSum(tree, 0, N - 1,
                                      Q[i, 1], Q[i, 2], 0) + " ");
            }
            else
            {
                Console.Write(-FindSum(tree, 0, N - 1,
                                       Q[i, 1], Q[i, 2], 0) + " ");
            }
        }
    }
  }
}
 
// This code is contributed by divyesh072019.


输出:
-2 2

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