📜  对于 Q 查询,X 和 Y 之间降雨量超过 K cms 的位置计数

📅  最后修改于: 2022-05-13 01:56:08.316000             🧑  作者: Mango

对于 Q 查询,X 和 Y 之间降雨量超过 K cms 的位置计数

给定一个由N个三元组(开始、结束、以 cms 为单位的降雨)组成的数组arr[][] ,定义降雨将从开始位置下降到结束位置,并以给定的降雨强度(以 cms 为单位)。还以数组query[][]的形式给出整数KQ查询(在每个查询中给出XY )。对于每个查询,任务是查找XY (含)之间降雨量超过K cms 的位置数量。

例子:

朴素的做法:遍历数组arr[][]并找到 location 的最大值。创建一个大小等于找到的最大位置的数组。然后对于每个降雨范围更新数组以获得聚合数组。现在对于每个查询遍历形成的数组并计算降雨量大于K cms 的位置数。

下面是上述方法的代码。

C++
// C++ program for above approach
#include 
using namespace std;
 
// Function to find number of locations
// with rainfall  more than K cms
vector count(vector arr, vector > Q,
                  int q, int k)
{
    vector ans;
    for (int i = 0; i < q; i++) {
        int temp = 0;
        for (int j = Q[i][0]; j <= Q[i][1]; j++) {
            if (arr[j] >= k)
                temp++;
        }
        ans.push_back(temp);
    }
    return ans;
}
 
// Function to find aggregate array
vector aggregateArray(vector > arr, int n)
{
    // To store the maximum location
    int m = 0;
 
    for (int i = 0; i < n; i++)
        m = max(m, arr[i][1]);
 
    // Array to store the aggregate values
    vector agg(m + 1);
    for (int i = 0; i < n; i++) {
        for (int j = arr[i][0]; j <= arr[i][1]; j++) {
            agg[j] += arr[i][2];
        }
    }
    return agg;
}
 
// Driver Code
int main()
{
    int N = 4;
    vector > arr = {
        { 1, 3, 5 }, { 2, 8, 3 }, { 5, 8, 2 }, { 7, 9, 6 }
    };
 
    // Storing aggregate array
    vector agg = aggregateArray(arr, N);
 
    int Q = 4;
    vector > queries
        = { { 1, 5 }, { 5, 9 }, { 2, 9 }, { 1, 9 } };
    int K = 5;
    vector ans = count(agg, queries, Q, K);
 
    // Printing answer to each query
    for (int i = 0; i < N; i++) {
        cout << ans[i] << endl;
    }
}


Python3
# python program for above approach
 
# Function to find number of locations
# with rainfall more than K cms
 
 
def count(arr, Q, q, k):
 
    ans = []
    for i in range(0, q):
        temp = 0
        for j in range(Q[i][0], Q[i][1] + 1):
            if (arr[j] >= k):
                temp += 1
 
        ans.append(temp)
 
    return ans
 
 
# Function to find aggregate array
def aggregateArray(arr, n):
 
    # To store the maximum location
    m = 0
 
    for i in range(0, n):
        m = max(m, arr[i][1])
 
    # Array to store the aggregate values
    agg = [0 for _ in range(m + 1)]
    for i in range(0, n):
        for j in range(arr[i][0], arr[i][1] + 1):
            agg[j] += arr[i][2]
 
    return agg
 
 
# Driver Code
if __name__ == "__main__":
 
    N = 4
    arr = [
        [1, 3, 5], [2, 8, 3],
        [5, 8, 2], [7, 9, 6]
    ]
 
    # Storing aggregate array
    agg = aggregateArray(arr, N)
 
    Q = 4
    queries = [[1, 5], [5, 9],
               [2, 9], [1, 9]]
 
    K = 5
    ans = count(agg, queries, Q, K)
 
    # Printing answer to each query
    for i in range(0, N):
        print(ans[i])
 
    # This code is contributed by rakeshsahni


Javascript


C++
// C++ program for above approach
#include 
using namespace std;
 
// Comparator function to sort
// the array in specific order
static bool comp(vector a, vector b)
{
    return (a[1] > b[1]);
}
 
// Function to find number of locations
// with rainfall  more than K cms
vector count(vector arr, vector > Q,
                  int q, int k)
{
 
    // Prefix sum array,
    // of count of locations having
    // rainfall greater than k cms
    int n = arr.size();
    vector arrPre(n);
 
    if (arr[0] >= k)
        arrPre[0] = 1;
    else
        arrPre[0] = 0;
 
    for (int i = 1; i < n; i++) {
 
        if (arr[i] >= k)
            arrPre[i] = arrPre[i - 1] + 1;
 
        else
            arrPre[i] = arrPre[i - 1];
    }
 
    // evaluating the queries
    vector ans;
    for (int i = 0; i < q; i++) {
        ans.push_back(arrPre[Q[i][1]]
                      - arrPre[Q[i][0] - 1]);
    }
    return ans;
}
 
// Function to find aggregate array
vector aggregateArray(vector > N, int n)
{
    // To store the maximum location
    int m = 0;
    for (int i = 0; i < n; i++)
        m = max(m, N[i][1]);
 
    // Array to store rainfall
    // of m locations sorting
    // input array based on end time,
    // in descending order
    vector arr(m + 1);
    sort(N.begin(), N.end(), comp);
 
    // To store start locn and
    // rainfall corresponding to it
    unordered_map start;
    int overlap = 0;
 
    for (int i = 0; i < n; i++) {
        // If two inputs have same end time,
        // we need to reposition them
        if (m < N[i][1])
            m++;
        else
            // Fill m with overlap,
            // till we reach current end location,
            // and keep checking if we've crossed
            // start time of previously recorded data
            // and decrement overlap(map)
            while (m > 0 && m != N[i][1])
                overlap -= start[m], arr[m--] = overlap;
 
        // To check if start time is crossed
        // of previously recorded data
        // and decrement overlap(map)
        overlap -= start[m];
 
        // Input data + previous recorded data
        arr[m] = overlap + N[i][2];
 
        // updating overlap with current data
        overlap += N[i][2];
 
        // storing start location with
        // corresponding rainfall data
        start[N[i][0] - 1] = N[i][2];
 
        // update m
        m--;
    }
    while (m >= N[n - 1][0])
 
        // fill out the left out indexes
        overlap -= start[m], arr[m--] = overlap;
    return arr;
}
 
// Driver Code
int main()
{
    int N = 4;
    vector > arr = {
        { 1, 3, 5 }, { 2, 8, 3 }, { 5, 8, 2 }, { 7, 9, 6 }
    };
    vector agg = aggregateArray(arr, N);
 
    int Q = 4;
 
    vector > queries
        = { { 1, 5 }, { 5, 9 }, { 2, 9 }, { 1, 9 } };
    int K = 5;
    vector ans = count(agg, queries, Q, K);
 
    // Printing answer to each query
    for (int i = 0; i < N; i++) {
        cout << ans[i] << endl;
    }
}


Python3
# Python program for above approach
 
# Function to find number of locations
# with rainfall  more than K cms
from functools import cmp_to_key
 
def mycmp(a, b):
    return b[1] - a[1]
 
def count(arr, Q, q, k):
 
    # Prefix sum array,
    # of count of locations having
    # rainfall greater than k cms
    n = len(arr)
    arrPre = [0 for i in range(n)]
 
    if (arr[0] >= k):
        arrPre[0] = 1
    else:
        arrPre[0] = 0
 
    for i in range(1,n):
 
        if (arr[i] >= k):
            arrPre[i] = arrPre[i - 1] + 1
 
        else:
            arrPre[i] = arrPre[i - 1]
 
    # evaluating the queries
    ans = []
    for i in range(q):
        ans.append(arrPre[Q[i][1]] - arrPre[Q[i][0] - 1])
     
    return ans
 
# Function to find aggregate array
def aggregateArray(N, n):
 
    # To store the maximum location
    m = 0
    for i in range(n):
        m = max(m, N[i][1])
 
    # Array to store rainfall
    # of m locations sorting
    # input array based on end time,
    # in descending order
    arr = [0 for i in range(m+1)]
    N.sort(key = cmp_to_key(mycmp))
 
    # To store start locn and
    # rainfall corresponding to it
    start = {}
    overlap = 0
 
    for i in range(n):
        # If two inputs have same end time,
        # we need to reposition them
        if (m < N[i][1]):
            m += 1
        else:
            # Fill m with overlap,
            # till we reach current end location,
            # and keep checking if we've crossed
            # start time of previously recorded data
            # and decreament overlap(map)
            while (m > 0 and m != N[i][1]):
                overlap -= start[m] if m in start else 0
                arr[m] = overlap
                m -= 1
 
        # To check if start time is crossed
        # of previously recorded data
        # and decreament overlap(map)
        overlap -= start[m] if m in start else 0
 
        # Input data + previous recorded data
        arr[m] = overlap + N[i][2]
 
        # updating overlap with current data
        overlap += N[i][2]
 
        # storing start location with
        # corresponding rainfall data
        start[N[i][0] - 1] = N[i][2]
 
        # update m
        m -= 1
 
    while (m >= N[n - 1][0]):
        # fill out the left out indexes
        overlap -=  start[m] if m in start else 0
        arr[m] = overlap
        m -= 1
 
    return arr
 
# Driver Code
N = 4
arr = [
    [ 1, 3, 5 ], [ 2, 8, 3 ],
    [ 5, 8, 2 ], [ 7, 9, 6 ]
]
agg = aggregateArray(arr, N)
Q = 4
queries = [ [ 1, 5 ], [ 5, 9 ],
        [ 2, 9 ], [ 1, 9 ] ]
K = 5
ans = count(agg, queries, Q, K)
 
# Printing answer to each query
for i in range(N):
    print(ans[i])
 
# This code is contributed by shinjanpatra


Javascript


Python3
# Python3 program for above approach
 
# Function to find number of locations with rainfall more than K cms
def count(arr, Q, q, k):
    n = len(arr)
 
    # prefix sum array
    prefix = [0 for _ in range(n)]
    if arr[0] >= k:
        prefix[0] = 1
    else:
        prefix[0] = 0
 
    for i in range(1, n-1):
        if arr[i] >= k:
            prefix[i] = prefix[i-1] + 1
        else:
            prefix[i] = prefix[i-1]
 
    # evaluate the queries using prefix sum array
    ans = []
    for i in range(0, q):
        start, end = Q[i][0]-1, Q[i][1]-1
 
        # if start is the minimum location possible, store prefix[end]
        if start == 0:
            count = prefix[end]
        else:
            count = prefix[end] - prefix[start-1]
             
        ans.append(count)
 
    return ans
 
# Function to find aggregate array
def aggregateArray(arr, n):
 
    # find maximum location possible
    m = -1
    for data in arr:
        m = max(m, data[1])
 
    # Array to store the aggregate values
    agg = [0 for _ in range(m + 1)]
 
    # update aggregate array at index start-1 and end locations
    for start, end, val in arr:
        agg[start-1] += val
        agg[end] -= val
 
    # iterate second time to fill the complete aggregate array
    # currRain holds amount of rainfall till current index
    currRain = 0
    for i in range(m+1):
        currRain += agg[i]
        agg[i] = currRain
 
    return agg
 
# Driver Code
if __name__ == "__main__":
    N = 4
    arr = [
    [1, 3, 5], [2, 8, 3],
    [5, 8, 2], [7, 9, 6]
    ]
 
    # Storing aggregate array
    agg = aggregateArray(arr, N)
 
    Q = 4
    queries = [[1, 5], [5, 9],
    [2, 9], [1, 9]]
 
    K = 5
    ans = count(agg, queries, Q, K)
 
    # Printing answer to each query
    for i in range(0, N):
        print(ans[i])
 
# This code is contributed by ultrainstinct


输出
4
5
7
8

时间复杂度: O(max(O(N*M), O(Q*M)))。
辅助空间:O(M)。
其中N是输入数, Q是查询数, M是最大位置。

有效的方法:给定的问题可以通过使用加权作业调度方法和前缀和来解决。这个问题可以分两部分解决,形成聚合数组,然后应用前缀和来有效地回答查询。请按照以下步骤解决给定的问题。

  • 根据结束位置对arr[][]进行排序。
  • 使用地图数据结构存储起始位置和重叠计数。
  • 对于每个结束位置,通过降雨数据 + 重叠更新聚合数组。
  • 在越过起始位置后,使用 Hashmaps 减少重叠。
  • 对于每个三元组,用开始时间更新 Hashmap。
  • 遍历并填充数组中的重叠,直到到达下一个三元组的结束位置。
  • 找到聚合数组后,使用前缀求和来查找每个查询的答案。

下面是上述方法的实现:

C++

// C++ program for above approach
#include 
using namespace std;
 
// Comparator function to sort
// the array in specific order
static bool comp(vector a, vector b)
{
    return (a[1] > b[1]);
}
 
// Function to find number of locations
// with rainfall  more than K cms
vector count(vector arr, vector > Q,
                  int q, int k)
{
 
    // Prefix sum array,
    // of count of locations having
    // rainfall greater than k cms
    int n = arr.size();
    vector arrPre(n);
 
    if (arr[0] >= k)
        arrPre[0] = 1;
    else
        arrPre[0] = 0;
 
    for (int i = 1; i < n; i++) {
 
        if (arr[i] >= k)
            arrPre[i] = arrPre[i - 1] + 1;
 
        else
            arrPre[i] = arrPre[i - 1];
    }
 
    // evaluating the queries
    vector ans;
    for (int i = 0; i < q; i++) {
        ans.push_back(arrPre[Q[i][1]]
                      - arrPre[Q[i][0] - 1]);
    }
    return ans;
}
 
// Function to find aggregate array
vector aggregateArray(vector > N, int n)
{
    // To store the maximum location
    int m = 0;
    for (int i = 0; i < n; i++)
        m = max(m, N[i][1]);
 
    // Array to store rainfall
    // of m locations sorting
    // input array based on end time,
    // in descending order
    vector arr(m + 1);
    sort(N.begin(), N.end(), comp);
 
    // To store start locn and
    // rainfall corresponding to it
    unordered_map start;
    int overlap = 0;
 
    for (int i = 0; i < n; i++) {
        // If two inputs have same end time,
        // we need to reposition them
        if (m < N[i][1])
            m++;
        else
            // Fill m with overlap,
            // till we reach current end location,
            // and keep checking if we've crossed
            // start time of previously recorded data
            // and decrement overlap(map)
            while (m > 0 && m != N[i][1])
                overlap -= start[m], arr[m--] = overlap;
 
        // To check if start time is crossed
        // of previously recorded data
        // and decrement overlap(map)
        overlap -= start[m];
 
        // Input data + previous recorded data
        arr[m] = overlap + N[i][2];
 
        // updating overlap with current data
        overlap += N[i][2];
 
        // storing start location with
        // corresponding rainfall data
        start[N[i][0] - 1] = N[i][2];
 
        // update m
        m--;
    }
    while (m >= N[n - 1][0])
 
        // fill out the left out indexes
        overlap -= start[m], arr[m--] = overlap;
    return arr;
}
 
// Driver Code
int main()
{
    int N = 4;
    vector > arr = {
        { 1, 3, 5 }, { 2, 8, 3 }, { 5, 8, 2 }, { 7, 9, 6 }
    };
    vector agg = aggregateArray(arr, N);
 
    int Q = 4;
 
    vector > queries
        = { { 1, 5 }, { 5, 9 }, { 2, 9 }, { 1, 9 } };
    int K = 5;
    vector ans = count(agg, queries, Q, K);
 
    // Printing answer to each query
    for (int i = 0; i < N; i++) {
        cout << ans[i] << endl;
    }
}

Python3

# Python program for above approach
 
# Function to find number of locations
# with rainfall  more than K cms
from functools import cmp_to_key
 
def mycmp(a, b):
    return b[1] - a[1]
 
def count(arr, Q, q, k):
 
    # Prefix sum array,
    # of count of locations having
    # rainfall greater than k cms
    n = len(arr)
    arrPre = [0 for i in range(n)]
 
    if (arr[0] >= k):
        arrPre[0] = 1
    else:
        arrPre[0] = 0
 
    for i in range(1,n):
 
        if (arr[i] >= k):
            arrPre[i] = arrPre[i - 1] + 1
 
        else:
            arrPre[i] = arrPre[i - 1]
 
    # evaluating the queries
    ans = []
    for i in range(q):
        ans.append(arrPre[Q[i][1]] - arrPre[Q[i][0] - 1])
     
    return ans
 
# Function to find aggregate array
def aggregateArray(N, n):
 
    # To store the maximum location
    m = 0
    for i in range(n):
        m = max(m, N[i][1])
 
    # Array to store rainfall
    # of m locations sorting
    # input array based on end time,
    # in descending order
    arr = [0 for i in range(m+1)]
    N.sort(key = cmp_to_key(mycmp))
 
    # To store start locn and
    # rainfall corresponding to it
    start = {}
    overlap = 0
 
    for i in range(n):
        # If two inputs have same end time,
        # we need to reposition them
        if (m < N[i][1]):
            m += 1
        else:
            # Fill m with overlap,
            # till we reach current end location,
            # and keep checking if we've crossed
            # start time of previously recorded data
            # and decreament overlap(map)
            while (m > 0 and m != N[i][1]):
                overlap -= start[m] if m in start else 0
                arr[m] = overlap
                m -= 1
 
        # To check if start time is crossed
        # of previously recorded data
        # and decreament overlap(map)
        overlap -= start[m] if m in start else 0
 
        # Input data + previous recorded data
        arr[m] = overlap + N[i][2]
 
        # updating overlap with current data
        overlap += N[i][2]
 
        # storing start location with
        # corresponding rainfall data
        start[N[i][0] - 1] = N[i][2]
 
        # update m
        m -= 1
 
    while (m >= N[n - 1][0]):
        # fill out the left out indexes
        overlap -=  start[m] if m in start else 0
        arr[m] = overlap
        m -= 1
 
    return arr
 
# Driver Code
N = 4
arr = [
    [ 1, 3, 5 ], [ 2, 8, 3 ],
    [ 5, 8, 2 ], [ 7, 9, 6 ]
]
agg = aggregateArray(arr, N)
Q = 4
queries = [ [ 1, 5 ], [ 5, 9 ],
        [ 2, 9 ], [ 1, 9 ] ]
K = 5
ans = count(agg, queries, Q, K)
 
# Printing answer to each query
for i in range(N):
    print(ans[i])
 
# This code is contributed by shinjanpatra

Javascript


输出
4
5
7
8

时间复杂度: O(max(NlogN, M))。
辅助空间: O(M)。
其中 N 是输入数,M 是最大位置。

高效方法2 :在上述方法中,我们首先根据结束时间对数组进行排序,然后计算需要O(NLogN)时间的聚合数组。我们可以通过如下计算聚合数组来改进这个时间:

让聚合数组为agg[]

我们首先迭代每个降雨数据。对于每个数据( startendval ),将val添加到agg[start]并从agg[end+1]中减去val ,因为降雨从位置 start 开始并持续到 end(包括)。

然后,我们对agg数组进行第二次迭代并跟踪当前降雨量currRain (初始化为 0) 通过将agg[index]的值添加到其中并将agg[index]更新为currRain

创建聚合数组后,使用前缀 sum来查找每个查询的答案。

下面是上述方法的实现:

Python3

# Python3 program for above approach
 
# Function to find number of locations with rainfall more than K cms
def count(arr, Q, q, k):
    n = len(arr)
 
    # prefix sum array
    prefix = [0 for _ in range(n)]
    if arr[0] >= k:
        prefix[0] = 1
    else:
        prefix[0] = 0
 
    for i in range(1, n-1):
        if arr[i] >= k:
            prefix[i] = prefix[i-1] + 1
        else:
            prefix[i] = prefix[i-1]
 
    # evaluate the queries using prefix sum array
    ans = []
    for i in range(0, q):
        start, end = Q[i][0]-1, Q[i][1]-1
 
        # if start is the minimum location possible, store prefix[end]
        if start == 0:
            count = prefix[end]
        else:
            count = prefix[end] - prefix[start-1]
             
        ans.append(count)
 
    return ans
 
# Function to find aggregate array
def aggregateArray(arr, n):
 
    # find maximum location possible
    m = -1
    for data in arr:
        m = max(m, data[1])
 
    # Array to store the aggregate values
    agg = [0 for _ in range(m + 1)]
 
    # update aggregate array at index start-1 and end locations
    for start, end, val in arr:
        agg[start-1] += val
        agg[end] -= val
 
    # iterate second time to fill the complete aggregate array
    # currRain holds amount of rainfall till current index
    currRain = 0
    for i in range(m+1):
        currRain += agg[i]
        agg[i] = currRain
 
    return agg
 
# Driver Code
if __name__ == "__main__":
    N = 4
    arr = [
    [1, 3, 5], [2, 8, 3],
    [5, 8, 2], [7, 9, 6]
    ]
 
    # Storing aggregate array
    agg = aggregateArray(arr, N)
 
    Q = 4
    queries = [[1, 5], [5, 9],
    [2, 9], [1, 9]]
 
    K = 5
    ans = count(agg, queries, Q, K)
 
    # Printing answer to each query
    for i in range(0, N):
        print(ans[i])
 
# This code is contributed by ultrainstinct
输出
4
5
7
8

时间复杂度: O(M)。

辅助空间: O(M)。

其中 M 是最大位置。