📌  相关文章
📜  范围查询以在给定数组上进行交替的加法和减法

📅  最后修改于: 2021-04-24 21:36:13             🧑  作者: Mango

给定N个整数的数组arr []Q个查询,其中每行由两个数字L和R组成,它们表示范围[L,R] ,任务是查找范围[ L,R]
例子:

天真的方法:天真的想法是针对每个查询从索引L迭代到R ,并找到交替添加和减去数组元素的值,并在执行操作后打印该值。
下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Structure to represent a range query
struct Query {
    int L, R;
};
 
// Function to find the result of
// alternatively adding and subtracting
// elements in the range [L, R]
int findResultUtil(int arr[],
                   int L, int R)
{
    int result = 0;
 
    // A boolean variable flag to
    // alternatively add and subtract
    bool flag = false;
 
    // Iterate from [L, R]
    for (int i = L; i <= R; i++) {
 
        // if flag is false, then
        // add & toggle the flag
        if (flag == false) {
            result = result + arr[i];
            flag = true;
        }
 
        // if flag is true subtract
        // and toggle the flag
        else {
            result = result - arr[i];
            flag = false;
        }
    }
 
    // Return the final result
    return result;
}
 
// Function to find the value
// for each query
void findResult(int arr[], int n,
                Query q[], int m)
{
 
    // Iterate for each query
    for (int i = 0; i < m; i++) {
        cout << findResultUtil(arr,
                               q[i].L,
                               q[i].R)
             << " ";
    }
}
 
// Driver Code
int main()
{
 
    // Given array
    int arr[] = { 10, 13, 15, 2, 45,
                  31, 22, 3, 27 };
 
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Given Queries
    Query q[] = { { 2, 5 }, { 6, 8 },
                  { 1, 7 }, { 4, 8 },
                  { 0, 5 } };
 
    int m = sizeof(q) / sizeof(q[0]);
 
    // Function Call
    findResult(arr, n, q, m);
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
 
class GFG{
 
// Structure to represent a range query
static class Query
{
    int L, R;
    public Query(int l, int r)
    {
        super();
        L = l;
        R = r;
    }
};
 
// Function to find the result of
// alternatively adding and subtracting
// elements in the range [L, R]
static int findResultUtil(int arr[],
                          int L, int R)
{
    int result = 0;
 
    // A boolean variable flag to
    // alternatively add and subtract
    boolean flag = false;
 
    // Iterate from [L, R]
    for(int i = L; i <= R; i++)
    {
         
        // If flag is false, then
        // add & toggle the flag
        if (flag == false)
        {
            result = result + arr[i];
            flag = true;
        }
 
        // If flag is true subtract
        // and toggle the flag
        else
        {
            result = result - arr[i];
            flag = false;
        }
    }
 
    // Return the final result
    return result;
}
 
// Function to find the value
// for each query
static void findResult(int arr[], int n,
                       Query q[], int m)
{
 
    // Iterate for each query
    for(int i = 0; i < m; i++)
    {
        System.out.print(findResultUtil(arr,
              q[i].L, q[i].R) + " ");
    }
}
 
// Driver Code
public static void main(String[] args)
{
 
    // Given array
    int arr[] = { 10, 13, 15, 2, 45,
                  31, 22, 3, 27 };
 
    int n = arr.length;
 
    // Given Queries
    Query q[] = { new Query(2, 5), new Query(6, 8),
                  new Query(1, 7), new Query(4, 8),
                  new Query(0, 5) };
 
    int m = q.length;
 
    // Function call
    findResult(arr, n, q, m);
}
}
 
// This code is contributed by Princi Singh


Python3
# Python3 program for the above approach
 
# Function to find the result of
# alternatively adding and subtracting
# elements in the range [L, R]
def findResultUtil(arr, L, R):
     
    result = 0
 
    # A boolean variable flag to
    # alternatively add and subtract
    flag = False
 
    # Iterate from [L, R]
    for i in range(L, R + 1):
         
        # If flag is False, then
        # add & toggle the flag
        if (flag == False):
            result = result + arr[i]
            flag = True
 
        # If flag is True subtract
        # and toggle the flag
        else:
            result = result - arr[i]
            flag = False
 
    # Return the final result
    return result
 
# Function to find the value
# for each query
def findResult(arr, n, q, m):
 
    # Iterate for each query
    for i in range(m):
        print(findResultUtil(arr,
                             q[i][0],
                             q[i][1]),
                             end = " ")
 
# Driver Code
if __name__ == '__main__':
 
    # Given array
    arr = [ 10, 13, 15, 2, 45,
            31, 22, 3, 27 ]
 
    n = len(arr)
 
    # Given Queries
    q = [ [ 2, 5 ], [ 6, 8 ],
          [ 1, 7 ], [ 4, 8 ],
          [ 0, 5 ] ]
 
    m = len(q)
 
    # Function Call
    findResult(arr, n, q, m)
 
# This code is contributed by mohit kumar 29


C#
// C# program for the above approach
using System;
class GFG{
 
// Structure to represent a range query
class Query
{
    public int L, R;
    public Query(int l, int r)
    {
        L = l;
        R = r;
    }
};
 
// Function to find the result of
// alternatively adding and subtracting
// elements in the range [L, R]
static int findResultUtil(int []arr,
                          int L, int R)
{
    int result = 0;
 
    // A bool variable flag to
    // alternatively add and subtract
    bool flag = false;
 
    // Iterate from [L, R]
    for(int i = L; i <= R; i++)
    {
         
        // If flag is false, then
        // add & toggle the flag
        if (flag == false)
        {
            result = result + arr[i];
            flag = true;
        }
 
        // If flag is true subtract
        // and toggle the flag
        else
        {
            result = result - arr[i];
            flag = false;
        }
    }
 
    // Return the readonly result
    return result;
}
 
// Function to find the value
// for each query
static void findResult(int []arr, int n,
                       Query []q, int m)
{
 
    // Iterate for each query
    for(int i = 0; i < m; i++)
    {
        Console.Write(findResultUtil(arr,
              q[i].L, q[i].R) + " ");
    }
}
 
// Driver Code
public static void Main(String[] args)
{
 
    // Given array
    int []arr = { 10, 13, 15, 2, 45,
                  31, 22, 3, 27 };
 
    int n = arr.Length;
 
    // Given Queries
    Query []q = { new Query(2, 5), new Query(6, 8),
                  new Query(1, 7), new Query(4, 8),
                  new Query(0, 5) };
 
    int m = q.Length;
 
    // Function call
    findResult(arr, n, q, m);
}
}
 
// This code is contributed by gauravrajput1


CPP
// C++ program for the above approach
#include 
using namespace std;
 
// Structure to represent a query
struct Query {
    int L, R;
};
 
// This function fills the Prefix Array
void fillPrefixArray(int arr[], int n,
                    int prefixArray[])
{
    // Initialise the prefix array
    prefixArray[0] = arr[0];
 
    // Iterate all the element of arr[]
    // and update the prefix array
    for (int i = 1; i < n; i++) {
 
        // If n is even then, add the
        // previous value of prefix array
        // with the current value of arr
        if (i % 2 == 0) {
 
            prefixArray[i]
                = prefixArray[i - 1]
                + arr[i];
        }
 
        // if n is odd, then subtract
        // the previous value of prefix
        // Array from current value
        else {
            prefixArray[i]
                = prefixArray[i - 1]
                - arr[i];
        }
    }
}
 
// Function to find the result of
// alternatively adding and subtracting
// elements in the range [L< R]
int findResultUtil(int prefixArray[],
                int L, int R)
{
    int result;
 
    // Case 1 : when L is zero
    if (L == 0) {
        result = prefixArray[R];
    }
 
    // Case 2 : When L is non zero
    else {
        result = prefixArray[R]
                - prefixArray[L - 1];
    }
 
    // If L is odd means range starts from
    // odd position multiply result by -1
    if (L & 1) {
        result = result * (-1);
    }
 
    // Return the final result
    return result;
}
 
// Function to find the sum of all
// alternative add and subtract
// between ranges [L, R]
void findResult(int arr[], int n,
                Query q[], int m)
{
 
    // Declare prefix array
    int prefixArray[n];
 
    // Function Call to fill prefix arr[]
    fillPrefixArray(arr, n, prefixArray);
 
    // Iterate for each query
    for (int i = 0; i < m; i++) {
 
        cout << findResultUtil(prefixArray,
                            q[i].L,
                            q[i].R)
            << " ";
    }
}
 
// Driver Code
int main()
{
 
    // Given array
    int arr[] = { 10, 13, 15, 2, 45,
                31, 22, 3, 27 };
 
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Given Queries
    Query q[] = { { 2, 5 }, { 6, 8 },
                { 1, 7 }, { 4, 8 },
                { 0, 5 } };
 
    int m = sizeof(q) / sizeof(q[0]);
 
    // Function Call
    findResult(arr, n, q, m);
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
class GFG{
 
// Structure to represent a query
static class Query
{
    int L, R;
 
    public Query(int l, int r)
    {
        super();
        L = l;
        R = r;
    }
};
 
// This function fills the Prefix Array
static void fillPrefixArray(int arr[], int n,
                            int prefixArray[])
{
    // Initialise the prefix array
    prefixArray[0] = arr[0];
 
    // Iterate all the element of arr[]
    // and update the prefix array
    for (int i = 1; i < n; i++)
    {
 
        // If n is even then, add the
        // previous value of prefix array
        // with the current value of arr
        if (i % 2 == 0)
        {
            prefixArray[i] = prefixArray[i - 1] +
                                           arr[i];
        }
 
        // if n is odd, then subtract
        // the previous value of prefix
        // Array from current value
        else
        {
            prefixArray[i] = prefixArray[i - 1] -
                                           arr[i];
        }
    }
}
 
// Function to find the result of
// alternatively adding and subtracting
// elements in the range [L< R]
static int findResultUtil(int prefixArray[],
                          int L, int R)
{
    int result;
 
    // Case 1 : when L is zero
    if (L == 0)
    {
        result = prefixArray[R];
    }
 
    // Case 2 : When L is non zero
    else
    {
        result = prefixArray[R] -
                   prefixArray[L - 1];
    }
 
    // If L is odd means range starts from
    // odd position multiply result by -1
    if (L % 2 == 1)
    {
        result = result * (-1);
    }
 
    // Return the final result
    return result;
}
 
// Function to find the sum of all
// alternative add and subtract
// between ranges [L, R]
static void findResult(int arr[], int n,
                         Query q[], int m)
{
 
    // Declare prefix array
    int []prefixArray = new int[n];
 
    // Function Call to fill prefix arr[]
    fillPrefixArray(arr, n, prefixArray);
 
    // Iterate for each query
    for (int i = 0; i < m; i++)
    {
        System.out.print(findResultUtil(
                           prefixArray, q[i].L,
                                        q[i].R) + " ");
    }
}
 
// Driver Code
public static void main(String[] args)
{
 
    // Given array
    int arr[] = { 10, 13, 15, 2, 45,
                31, 22, 3, 27 };
 
    int n = arr.length;
 
    // Given Queries
    Query q[] = {new Query( 2, 5 ), new Query( 6, 8 ),
                 new Query( 1, 7 ), new Query( 4, 8 ),
                 new Query( 0, 5 )};
 
    int m = q.length;
 
    // Function Call
    findResult(arr, n, q, m);
}
}
 
// This code is contributed by PrinciRaj1992


C#
// C# program for the above approach
using System;
class GFG{
 
// Structure to represent a query
class Query
{
   public  int L, R;
 
    public Query(int l, int r)
    {
        L = l;
        R = r;
    }
};
 
// This function fills the Prefix Array
static void fillPrefixArray(int []arr, int n,
                            int []prefixArray)
{
    // Initialise the prefix array
    prefixArray[0] = arr[0];
 
    // Iterate all the element of []arr
    // and update the prefix array
    for (int i = 1; i < n; i++)
    {
 
        // If n is even then, add the
        // previous value of prefix array
        // with the current value of arr
        if (i % 2 == 0)
        {
            prefixArray[i] = prefixArray[i - 1] +
                                         arr[i];
        }
 
        // if n is odd, then subtract
        // the previous value of prefix
        // Array from current value
        else
        {
            prefixArray[i] = prefixArray[i - 1] -
                                         arr[i];
        }
    }
}
 
// Function to find the result of
// alternatively adding and subtracting
// elements in the range [L< R]
static int findResultUtil(int []prefixArray,
                          int L, int R)
{
    int result;
 
    // Case 1 : when L is zero
    if (L == 0)
    {
        result = prefixArray[R];
    }
 
    // Case 2 : When L is non zero
    else
    {
        result = prefixArray[R] -
                 prefixArray[L - 1];
    }
 
    // If L is odd means range starts from
    // odd position multiply result by -1
    if (L % 2 == 1)
    {
        result = result * (-1);
    }
 
    // Return the readonly result
    return result;
}
 
// Function to find the sum of all
// alternative add and subtract
// between ranges [L, R]
static void findResult(int []arr, int n,
                       Query []q, int m)
{
 
    // Declare prefix array
    int []prefixArray = new int[n];
 
    // Function Call to fill prefix []arr
    fillPrefixArray(arr, n, prefixArray);
 
    // Iterate for each query
    for (int i = 0; i < m; i++)
    {
        Console.Write(findResultUtil(
                           prefixArray, q[i].L,
                                        q[i].R) + " ");
    }
}
 
// Driver Code
public static void Main(String[] args)
{
 
    // Given array
    int []arr = { 10, 13, 15, 2, 45,
                31, 22, 3, 27 };
 
    int n = arr.Length;
 
    // Given Queries
    Query []q = {new Query( 2, 5 ), new Query( 6, 8 ),
                 new Query( 1, 7 ), new Query( 4, 8 ),
                 new Query( 0, 5 )};
 
    int m = q.Length;
 
    // Function Call
    findResult(arr, n, q, m);
}
}
 
// This code is contributed by Rohit_ranjan


输出:
27 46 -33 60 24







时间复杂度: O(N * Q)
辅助空间: O(1)
高效的方法:高效的方法是使用Prefix Sum Array解决上述问题。步骤如下:

  1. 将前缀数组的第一个元素(例如pre [] )初始化为arr []的第一个元素。
  2. 1到N-1遍历索引,并从pre [i-1]中交替添加和减去arr [i]的元素,并将其存储在pre [i]中以构成前缀数组。
  3. 现在,遍历每个查询从1到Q ,并根据以下情况查找结果:
    • 情况1:如果L为零,则结果为pre [R]
    • 情况2:如果L不为零,则使用以下公式查找结果:
result = Query(L, R) = pre[R] – pre[L - 1]


  • 如果L为奇数,则将上述结果乘以-1

下面是上述方法的实现:

CPP

// C++ program for the above approach
#include 
using namespace std;
 
// Structure to represent a query
struct Query {
    int L, R;
};
 
// This function fills the Prefix Array
void fillPrefixArray(int arr[], int n,
                    int prefixArray[])
{
    // Initialise the prefix array
    prefixArray[0] = arr[0];
 
    // Iterate all the element of arr[]
    // and update the prefix array
    for (int i = 1; i < n; i++) {
 
        // If n is even then, add the
        // previous value of prefix array
        // with the current value of arr
        if (i % 2 == 0) {
 
            prefixArray[i]
                = prefixArray[i - 1]
                + arr[i];
        }
 
        // if n is odd, then subtract
        // the previous value of prefix
        // Array from current value
        else {
            prefixArray[i]
                = prefixArray[i - 1]
                - arr[i];
        }
    }
}
 
// Function to find the result of
// alternatively adding and subtracting
// elements in the range [L< R]
int findResultUtil(int prefixArray[],
                int L, int R)
{
    int result;
 
    // Case 1 : when L is zero
    if (L == 0) {
        result = prefixArray[R];
    }
 
    // Case 2 : When L is non zero
    else {
        result = prefixArray[R]
                - prefixArray[L - 1];
    }
 
    // If L is odd means range starts from
    // odd position multiply result by -1
    if (L & 1) {
        result = result * (-1);
    }
 
    // Return the final result
    return result;
}
 
// Function to find the sum of all
// alternative add and subtract
// between ranges [L, R]
void findResult(int arr[], int n,
                Query q[], int m)
{
 
    // Declare prefix array
    int prefixArray[n];
 
    // Function Call to fill prefix arr[]
    fillPrefixArray(arr, n, prefixArray);
 
    // Iterate for each query
    for (int i = 0; i < m; i++) {
 
        cout << findResultUtil(prefixArray,
                            q[i].L,
                            q[i].R)
            << " ";
    }
}
 
// Driver Code
int main()
{
 
    // Given array
    int arr[] = { 10, 13, 15, 2, 45,
                31, 22, 3, 27 };
 
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // Given Queries
    Query q[] = { { 2, 5 }, { 6, 8 },
                { 1, 7 }, { 4, 8 },
                { 0, 5 } };
 
    int m = sizeof(q) / sizeof(q[0]);
 
    // Function Call
    findResult(arr, n, q, m);
    return 0;
}

Java

// Java program for the above approach
import java.util.*;
class GFG{
 
// Structure to represent a query
static class Query
{
    int L, R;
 
    public Query(int l, int r)
    {
        super();
        L = l;
        R = r;
    }
};
 
// This function fills the Prefix Array
static void fillPrefixArray(int arr[], int n,
                            int prefixArray[])
{
    // Initialise the prefix array
    prefixArray[0] = arr[0];
 
    // Iterate all the element of arr[]
    // and update the prefix array
    for (int i = 1; i < n; i++)
    {
 
        // If n is even then, add the
        // previous value of prefix array
        // with the current value of arr
        if (i % 2 == 0)
        {
            prefixArray[i] = prefixArray[i - 1] +
                                           arr[i];
        }
 
        // if n is odd, then subtract
        // the previous value of prefix
        // Array from current value
        else
        {
            prefixArray[i] = prefixArray[i - 1] -
                                           arr[i];
        }
    }
}
 
// Function to find the result of
// alternatively adding and subtracting
// elements in the range [L< R]
static int findResultUtil(int prefixArray[],
                          int L, int R)
{
    int result;
 
    // Case 1 : when L is zero
    if (L == 0)
    {
        result = prefixArray[R];
    }
 
    // Case 2 : When L is non zero
    else
    {
        result = prefixArray[R] -
                   prefixArray[L - 1];
    }
 
    // If L is odd means range starts from
    // odd position multiply result by -1
    if (L % 2 == 1)
    {
        result = result * (-1);
    }
 
    // Return the final result
    return result;
}
 
// Function to find the sum of all
// alternative add and subtract
// between ranges [L, R]
static void findResult(int arr[], int n,
                         Query q[], int m)
{
 
    // Declare prefix array
    int []prefixArray = new int[n];
 
    // Function Call to fill prefix arr[]
    fillPrefixArray(arr, n, prefixArray);
 
    // Iterate for each query
    for (int i = 0; i < m; i++)
    {
        System.out.print(findResultUtil(
                           prefixArray, q[i].L,
                                        q[i].R) + " ");
    }
}
 
// Driver Code
public static void main(String[] args)
{
 
    // Given array
    int arr[] = { 10, 13, 15, 2, 45,
                31, 22, 3, 27 };
 
    int n = arr.length;
 
    // Given Queries
    Query q[] = {new Query( 2, 5 ), new Query( 6, 8 ),
                 new Query( 1, 7 ), new Query( 4, 8 ),
                 new Query( 0, 5 )};
 
    int m = q.length;
 
    // Function Call
    findResult(arr, n, q, m);
}
}
 
// This code is contributed by PrinciRaj1992

C#

// C# program for the above approach
using System;
class GFG{
 
// Structure to represent a query
class Query
{
   public  int L, R;
 
    public Query(int l, int r)
    {
        L = l;
        R = r;
    }
};
 
// This function fills the Prefix Array
static void fillPrefixArray(int []arr, int n,
                            int []prefixArray)
{
    // Initialise the prefix array
    prefixArray[0] = arr[0];
 
    // Iterate all the element of []arr
    // and update the prefix array
    for (int i = 1; i < n; i++)
    {
 
        // If n is even then, add the
        // previous value of prefix array
        // with the current value of arr
        if (i % 2 == 0)
        {
            prefixArray[i] = prefixArray[i - 1] +
                                         arr[i];
        }
 
        // if n is odd, then subtract
        // the previous value of prefix
        // Array from current value
        else
        {
            prefixArray[i] = prefixArray[i - 1] -
                                         arr[i];
        }
    }
}
 
// Function to find the result of
// alternatively adding and subtracting
// elements in the range [L< R]
static int findResultUtil(int []prefixArray,
                          int L, int R)
{
    int result;
 
    // Case 1 : when L is zero
    if (L == 0)
    {
        result = prefixArray[R];
    }
 
    // Case 2 : When L is non zero
    else
    {
        result = prefixArray[R] -
                 prefixArray[L - 1];
    }
 
    // If L is odd means range starts from
    // odd position multiply result by -1
    if (L % 2 == 1)
    {
        result = result * (-1);
    }
 
    // Return the readonly result
    return result;
}
 
// Function to find the sum of all
// alternative add and subtract
// between ranges [L, R]
static void findResult(int []arr, int n,
                       Query []q, int m)
{
 
    // Declare prefix array
    int []prefixArray = new int[n];
 
    // Function Call to fill prefix []arr
    fillPrefixArray(arr, n, prefixArray);
 
    // Iterate for each query
    for (int i = 0; i < m; i++)
    {
        Console.Write(findResultUtil(
                           prefixArray, q[i].L,
                                        q[i].R) + " ");
    }
}
 
// Driver Code
public static void Main(String[] args)
{
 
    // Given array
    int []arr = { 10, 13, 15, 2, 45,
                31, 22, 3, 27 };
 
    int n = arr.Length;
 
    // Given Queries
    Query []q = {new Query( 2, 5 ), new Query( 6, 8 ),
                 new Query( 1, 7 ), new Query( 4, 8 ),
                 new Query( 0, 5 )};
 
    int m = q.Length;
 
    // Function Call
    findResult(arr, n, q, m);
}
}
 
// This code is contributed by Rohit_ranjan

输出:

27 46 -33 60 24






时间复杂度: O(N + Q)
辅助空间: O(N)