📌  相关文章
📜  两个等和段范围查询

📅  最后修改于: 2021-10-28 01:36:30             🧑  作者: Mango

给定一个由N 个正整数组成的数组arr[] ,以及一些由范围[L, R]组成的查询,任务是找到给定索引范围内的子数组是否可以分为非连续的两个连续部分零长度和相等的总和。
例子:

一个简单的解决方案是遍历整个范围并计算范围的总和。然后,我们将再次遍历整个数组。我们将从索引“L”开始总结元素。如果在任何一步,我们发现当前和是范围总和的一半,则可以将范围表示的子数组分成相等的两半。使用这种方法回答查询可能需要 O(n) 时间。
更好的解决方案是使用前缀和数组。首先,我们创建一个 arr 的前缀和数组p_arr 。现在,使用“p_arr”,我们可以在 O(1) 时间内确定“L”到“R”范围内所有元素的总和。一旦有了总和,我们需要确定是否存在从L 到 R-1的索引“i”,使得原始数组的 L 到 i 之间所有数字的总和是范围总和的一半。因为,我们可以简单地将前缀和数组 ‘p_arr’ 中的所有值插入到一个无序映射中。

因此,回答查询的时间复杂度变为 O(1)。
下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
 
// Function to find the required prefix sum
void prefixSum(int* p_arr, int* arr, int n)
{
    p_arr[0] = arr[0];
    for (int i = 1; i < n; i++)
        p_arr[i] = arr[i] + p_arr[i - 1];
}
 
// Function to hash all the values of prefix
// sum array in an unordered map
void hashPrefixSum(int* p_arr, int n, unordered_set& q)
{
    for (int i = 0; i < n; i++)
        q.insert(p_arr[i]);
}
 
// Function to check if a range
// can be divided into two equal parts
void canDivide(int* p_arr, int n,
               unordered_set& q, int l, int r)
{
    // To store the value of sum
    // of entire range
    int sum;
 
    if (l == 0)
        sum = p_arr[r];
    else
        sum = p_arr[r] - p_arr[l - 1];
 
    // If value of sum is odd
    if (sum % 2 == 1) {
        cout << "No" << endl;
        return;
    }
 
    // To store p_arr[l-1]
    int beg = 0;
 
    if (l != 0)
        beg = p_arr[l - 1];
 
    // If the value exists in the map
    if (q.find(beg + sum / 2) != q.end())
        cout << "Yes" << endl;
    else
        cout << "No" << endl;
}
 
// Driver code
int main()
{
    int arr[] = { 1, 1, 2, 3 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // prefix-sum array
    int p_arr[n];
 
    prefixSum(p_arr, arr, n);
 
    // Map to store the values of prefix-sum
    unordered_set q;
 
    hashPrefixSum(p_arr, n, q);
 
    // Perform queries
    canDivide(p_arr, n, q, 0, 1);
    canDivide(p_arr, n, q, 1, 3);
    canDivide(p_arr, n, q, 1, 2);
 
    return 0;
}


Java
// Java implementation of the approach
import java.util.*;
class GFG {
 
// Function to find the required prefix sum
static void prefixSum(int[] p_arr, int[] arr, int n)
{
    p_arr[0] = arr[0];
    for (int i = 1; i < n; i++)
        p_arr[i] = arr[i] + p_arr[i - 1];
}
  
// Function to q all the values of prefix
// sum array in an unordered map
static void qPrefixSum(int[]p_arr, int n, HashSetq)
{
    for (int i = 0; i < n; i++)
        q.add(p_arr[i]);
}
  
// Function to check if a range
// can be divided into two equal parts
static void canDivide(int[] p_arr, int n,
               HashSetq, int l, int r)
{
    // To store the value of sum
    // of entire range
    int sum;
  
    if (l == 0)
        sum = p_arr[r];
    else
        sum = p_arr[r] - p_arr[l - 1];
  
    // If value of sum is odd
    if (sum % 2 == 1) {
        System.out.println("No");
        return;
    }
  
    // To store p_arr[l-1]
    int beg = 0;
  
    if (l != 0)
        beg = p_arr[l - 1];
  
    // If the value exists in the map
    if(q.contains(beg + sum / 2) && (beg + sum / 2)!=(int)q.toArray()[ q.size()-1 ] )
        System.out.println("Yes");
    else
        System.out.println("No");
}
  
// Driver code
 public static void main(String[] args) {
   int arr[] = { 1, 1, 2, 3 };
    int n = arr.length;
  
    // prefix-sum array
    int p_arr[] = new int[n];
  
    prefixSum(p_arr, arr, n);
  
    // Map to store the values of prefix-sum
    HashSet q = new HashSet<>();
  
    qPrefixSum(p_arr, n, q);
  
    // Perform queries
    canDivide(p_arr, n, q, 0, 1);
    canDivide(p_arr, n, q, 1, 3);
    canDivide(p_arr, n, q, 1, 2);
    }
}
 
// This code contributed by Rajput-Ji


Python3
# Python3 implementation of the approach
 
# Function to find the required prefix Sum
def prefixSum(p_arr, arr, n):
 
    p_arr[0] = arr[0]
    for i in range(1, n):
        p_arr[i] = arr[i] + p_arr[i - 1]
 
# Function to hash all the values of
# prefix Sum array in an unordered map
def hashPrefixSum(p_arr, n, q):
 
    for i in range(n):
        q[p_arr[i]] = 1
 
# Function to check if a range
# can be divided into two equal parts
def canDivide(p_arr, n, q, l, r):
     
    # To store the value of Sum
    # of entire range
    Sum = 0
 
    if (l == 0):
        Sum = p_arr[r]
    else:
        Sum = p_arr[r] - p_arr[l - 1]
 
    # If value of Sum is odd
    if (Sum % 2 == 1):
        print("No")
        return
     
    # To store p_arr[l-1]
    beg = 0
 
    if (l != 0):
        beg = p_arr[l - 1]
 
    # If the value exists in the map
    if (beg + Sum // 2 in q.keys()):
        print("Yes")
    else:
        print("No")
 
# Driver code
arr = [1, 1, 2, 3]
n = len(arr)
 
# prefix-Sum array
p_arr = [0 for i in range(n)]
 
prefixSum(p_arr, arr, n)
 
# Map to store the values
# of prefix-Sum
q = dict()
 
hashPrefixSum(p_arr, n, q)
 
# Perform queries
canDivide(p_arr, n, q, 0, 1)
canDivide(p_arr, n, q, 1, 3)
canDivide(p_arr, n, q, 1, 2)
 
# This code is contributed
# by mohit kumar


C#
// C# implementation of the approach
using System;
using System.Collections.Generic;
 
class GFG
{
 
// Function to find the required prefix sum
static void prefixSum(int[] p_arr, int[] arr, int n)
{
    p_arr[0] = arr[0];
    for (int i = 1; i < n; i++)
        p_arr[i] = arr[i] + p_arr[i - 1];
}
 
// Function to q all the values of prefix
// sum array in an unordered map
static void qPrefixSum(int[]p_arr, int n, HashSetq)
{
    for (int i = 0; i < n; i++)
        q.Add(p_arr[i]);
}
 
// Function to check if a range
// can be divided into two equal parts
static void canDivide(int[] p_arr, int n,
            HashSetq, int l, int r)
{
    // To store the value of sum
    // of entire range
    int sum;
 
    if (l == 0)
        sum = p_arr[r];
    else
        sum = p_arr[r] - p_arr[l - 1];
 
    // If value of sum is odd
    if (sum % 2 == 1)
    {
        Console.WriteLine("No");
        return;
    }
 
    // To store p_arr[l-1]
    int beg = 0;
 
    if (l != 0)
        beg = p_arr[l - 1];
 
    // If the value exists in the map
    if(q.Contains(beg + sum / 2) )
        Console.WriteLine("Yes");
    else
        Console.WriteLine("No");
}
 
// Driver code
public static void Main(String[] args)
{
    int []arr = { 1, 1, 2, 3 };
    int n = arr.Length;
 
    // prefix-sum array
    int []p_arr = new int[n];
 
    prefixSum(p_arr, arr, n);
 
    // Map to store the values of prefix-sum
    HashSet q = new HashSet ();
 
    qPrefixSum(p_arr, n, q);
 
    // Perform queries
    canDivide(p_arr, n, q, 0, 1);
    canDivide(p_arr, n, q, 1, 3);
    canDivide(p_arr, n, q, 1, 2);
}
}
 
// This code has been contributed by 29AjayKumar


Javascript


输出:
Yes
Yes
No