给定大小为N的数组arr[]和由以下两种类型的查询组成的矩阵Q :
- 1 LR :打印位于 [L, R] 范围内的元素数量。
- 2 ix :设置 arr[i] = x
例子:
Input: arr[] = {1, 2, 2, 3, 4, 4, 5, 6}, Q = {{1, {3, 5}}, {1, {2, 4}}, {1, {1, 2}}, {2, {1, 7}}, {1, {1, 2}}}
Output: 4 5 3 2
Explanation:
Array elements from the range [3, 5] are {3, 4, 4, 5}
Array elements from the range [2, 4] are {2, 2, 3, 4, 4}
Array elements from the range [1, 2] are {1, 2, 2}
Replacing arr[1] by 7 modifies the array to {1, 7, 2, 3, 4, 4, 5, 6}
Elements that lie in range [1, 2] are {1, 2}
Input: arr = {5, 5, 1, 3, 4, 4, 2, 3}, Q = {{1, {3, 6}}, {1, {2, 4}}, {1, {10, 20}}}
Output: 6 5 0
Explanation:
Array elements from the range [3, 6] are {3, 3, 4, 4, 5, 5}
Array elements from the range [2, 4] are {2, 3, 3, 4, 4}
No element from the range [10, 20] exists in the array.
天真的方法:
解决这个问题最简单的方法如下:
- 对于(1 LR)类型的查询,遍历整个数组并计算数组中元素的数量,使得L ≤ arr[i] ≤ R 。最后,打印计数。
- 对于类型(2 ix)的查询,将arr[i]替换为x 。
下面是上述方法的实现:
C++
// C++ code for queries for number
// of elements that lie in range
// [l, r] (with updates)
#include
using namespace std;
// Function to set arr[index] = x
void setElement(int* arr, int n,
int index, int x)
{
arr[index] = x;
}
// Function to get count of elements
// that lie in range [l, r]
int getCount(int* arr, int n,
int l, int r)
{
int count = 0;
// Traverse array
for (int i = 0; i < n; i++) {
// If element lies in the
// range [L, R]
if (arr[i] >= l
&& arr[i] <= r) {
// Increase count
count++;
}
}
return count;
}
// Function to solve each query
void SolveQuery(int arr[], int n,
vector > >
Q)
{
int x;
for (int i = 0; i < Q.size(); i++) {
if (Q[i].first == 1) {
x = getCount(arr, n,
Q[i].second.first,
Q[i].second.second);
cout << x << " ";
}
else {
setElement(arr, n,
Q[i].second.first,
Q[i].second.second);
}
}
}
// Driver Code
int main()
{
int arr[] = { 1, 2, 2, 3, 4, 4, 5, 6 };
int n = sizeof(arr) / sizeof(arr[0]);
vector > > Q
= { { 1, { 3, 5 } },
{ 1, { 2, 4 } },
{ 1, { 1, 2 } },
{ 2, { 1, 7 } },
{ 1, { 1, 2 } } };
SolveQuery(arr, n, Q);
return 0;
}
Java
// Java code for queries for number
// of elements that lie in range
// [l, r] (with updates)
import java.util.*;
import java.lang.*;
class GFG{
// Function to set arr[index] = x
static void setElement(int[] arr, int n,
int index, int x)
{
arr[index] = x;
}
// Function to get count of elements
// that lie in range [l, r]
static int getCount(int[] arr, int n,
int l, int r)
{
int count = 0;
// Traverse array
for(int i = 0; i < n; i++)
{
// If element lies in the
// range [L, R]
if (arr[i] >= l && arr[i] <= r)
{
// Increase count
count++;
}
}
return count;
}
// Function to solve each query
static void SolveQuery(int arr[], int n,
ArrayList> Q)
{
int x;
for(int i = 0; i < Q.size(); i++)
{
if (Q.get(i).get(0) == 1)
{
x = getCount(arr, n,
Q.get(i).get(1),
Q.get(i).get(2));
System.out.print(x + " ");
}
else
{
setElement(arr, n,
Q.get(i).get(1),
Q.get(i).get(2));
}
}
}
// Driver code
public static void main (String[] args)
{
int arr[] = { 1, 2, 2, 3, 4, 4, 5, 6 };
int n = arr.length;
ArrayList> Q = new ArrayList<>();
Q.add(Arrays.asList(1, 3, 5));
Q.add(Arrays.asList(1, 2, 4));
Q.add(Arrays.asList(1, 1, 2));
Q.add(Arrays.asList(2, 1, 7));
Q.add(Arrays.asList(1, 1, 2));
SolveQuery(arr, n, Q);
}
}
// This code is contributed by offbeat
Python3
# Python3 code for queries for number
# of elements that lie in range
# [l, r] (with updates)
from typing import Generic, List, TypeVar
T = TypeVar('T')
V = TypeVar('V')
class Pair(Generic[V, T]):
def __init__(self, first: V, second: T) -> None:
self.first = first
self.second = second
# Function to set arr[index] = x
def setElement(arr: List[int], n: int,
index: int, x: int) -> None:
arr[index] = x
# Function to get count of elements
# that lie in range [l, r]
def getCount(arr: List[int], n: int,
l: int, r: int) -> int:
count = 0
# Traverse array
for i in range(n):
# If element lies in the
# range [L, R]
if (arr[i] >= l and arr[i] <= r):
# Increase count
count += 1
return count
# Function to solve each query
def SolveQuery(arr: List[int], n: int,
Q: List[Pair[int, Pair[int, int]]]):
x = 0
for i in range(len(Q)):
if (Q[i].first == 1):
x = getCount(arr, n, Q[i].second.first,
Q[i].second.second)
print(x, end = " ")
else:
setElement(arr, n, Q[i].second.first,
Q[i].second.second)
# Driver Code
if __name__ == "__main__":
arr = [ 1, 2, 2, 3, 4, 4, 5, 6 ]
n = len(arr)
Q = [ Pair(1, Pair(3, 5)),
Pair(1, Pair(2, 4)),
Pair(1, Pair(1, 2)),
Pair(2, Pair(1, 7)),
Pair(1, Pair(1, 2)) ]
SolveQuery(arr, n, Q)
# This code is contributed by sanjeev2552
C#
// C# code for queries for number
// of elements that lie in range
// [l, r] (with updates)
using System;
using System.Collections.Generic;
class GFG{
// Function to set arr[index] = x
static void setElement(int[] arr, int n,
int index, int x)
{
arr[index] = x;
}
// Function to get count of elements
// that lie in range [l, r]
static int getCount(int[] arr, int n,
int l, int r)
{
int count = 0;
// Traverse array
for(int i = 0; i < n; i++)
{
// If element lies in the
// range [L, R]
if (arr[i] >= l && arr[i] <= r)
// Increase count
count += 1;
}
return count;
}
// Function to solve each query
static void SolveQuery(int[] arr, int n,
List> Q)
{
int x;
for(int i = 0; i < Q.Count; i++)
{
if (Q[i][0] == 1)
{
x = getCount(arr, n,
Q[i][1],
Q[i][2]);
Console.Write(x + " ");
}
else
{
setElement(arr, n,
Q[i][1],
Q[i][2]);
}
}
}
// Driver code
public static void Main(string[] args)
{
int[] arr = { 1, 2, 2, 3, 4, 4, 5, 6 };
int n = arr.Length;
List> myList = new List>();
myList.Add(new List{ 1, 3, 5 });
myList.Add(new List{ 1, 2, 4 });
myList.Add(new List{ 1, 1, 2 });
myList.Add(new List{ 2, 1, 7 });
myList.Add(new List{ 1, 1, 2 });
SolveQuery(arr, n, myList);
}
}
// This code is contributed by grand_master
C++
// C++ code for queries for number
// of elements that lie in range
// [l, r] (with updates)
#include
using namespace std;
class FenwickTree {
public:
int* BIT;
int N;
FenwickTree(int N)
{
this->N = N;
BIT = new int[N];
for (int i = 0; i < N; i++) {
BIT[i] = 0;
}
}
// Traverse all ancestors and
// increase frequency of index
void update(int index, int increment)
{
while (index < N) {
// Increase count of the current
// node of BIT Tree
BIT[index] += increment;
// Update index to that of parent
// in update View
index += (index & -index);
}
}
// Function to return the
// sum of arr[0..index]
int getSum(int index)
{
int sum = 0;
// Traverse ancestors of
// BITree[index]
while (index > 0) {
// Add current element of
// BITree to sum
sum += BIT[index];
// Move index to parent node in
// getSum View
index -= (index & -index);
}
return sum;
}
};
// Function to set arr[index] = x
void setElement(int* arr, int n,
int index, int x,
FenwickTree* fenTree)
{
int removedElement = arr[index];
fenTree->update(removedElement, -1);
arr[index] = x;
fenTree->update(x, 1);
}
// Function to get count of
// elements that lie in
// range [l, r]
int getCount(int* arr, int n,
int l, int r,
FenwickTree* fenTree)
{
int count = fenTree->getSum(r)
- fenTree->getSum(l - 1);
return count;
}
// Function to solve each query
void SolveQuery(int arr[], int n,
vector > >
Q)
{
int N = 100001;
FenwickTree* fenTree = new FenwickTree(N);
for (int i = 0; i < n; i++) {
fenTree->update(arr[i], 1);
}
int x;
for (int i = 0; i < Q.size(); i++) {
if (Q[i].first == 1) {
x = getCount(arr, n,
Q[i].second.first,
Q[i].second.second,
fenTree);
cout << x << " ";
}
else {
setElement(arr, n,
Q[i].second.first,
Q[i].second.second,
fenTree);
}
}
}
// Driver Code
int main()
{
int arr[] = { 1, 2, 2, 3,
4, 4, 5, 6 };
int n = sizeof(arr) / sizeof(arr[0]);
vector > > Q
= { { 1, { 3, 5 } },
{ 1, { 2, 4 } },
{ 1, { 1, 2 } },
{ 2, { 1, 7 } },
{ 1, { 1, 2 } } };
SolveQuery(arr, n, Q);
return 0;
}
4 5 3 2
时间复杂度: O(Q * N)
辅助空间: O(1)
有效的方法:
上述方法可以使用 Fenwick Tree 进行优化。请按照以下步骤解决问题:
- 从给定的数组构造一个 Fenwick 树。
- Fenwick树将表示为一个大小等于数组中最大元素的数组,这样数组元素就可以作为索引(思路和这个方法类似)。
- 通过调用Fenwick树的update方法遍历数组,增加每个元素出现的频率。
- 对于每个类型为(1 LR) 的查询,调用 Fenwick 树的getSum方法。类型 1 查询的答案将是:
getSum(R) – getSum(L – 1)
- 对于每个类型为(2 ix) 的查询,调用 Fenwick 树的update方法来增加添加元素的频率并减少要替换的元素的数量。
下面是上述方法的实现:
C++
// C++ code for queries for number
// of elements that lie in range
// [l, r] (with updates)
#include
using namespace std;
class FenwickTree {
public:
int* BIT;
int N;
FenwickTree(int N)
{
this->N = N;
BIT = new int[N];
for (int i = 0; i < N; i++) {
BIT[i] = 0;
}
}
// Traverse all ancestors and
// increase frequency of index
void update(int index, int increment)
{
while (index < N) {
// Increase count of the current
// node of BIT Tree
BIT[index] += increment;
// Update index to that of parent
// in update View
index += (index & -index);
}
}
// Function to return the
// sum of arr[0..index]
int getSum(int index)
{
int sum = 0;
// Traverse ancestors of
// BITree[index]
while (index > 0) {
// Add current element of
// BITree to sum
sum += BIT[index];
// Move index to parent node in
// getSum View
index -= (index & -index);
}
return sum;
}
};
// Function to set arr[index] = x
void setElement(int* arr, int n,
int index, int x,
FenwickTree* fenTree)
{
int removedElement = arr[index];
fenTree->update(removedElement, -1);
arr[index] = x;
fenTree->update(x, 1);
}
// Function to get count of
// elements that lie in
// range [l, r]
int getCount(int* arr, int n,
int l, int r,
FenwickTree* fenTree)
{
int count = fenTree->getSum(r)
- fenTree->getSum(l - 1);
return count;
}
// Function to solve each query
void SolveQuery(int arr[], int n,
vector > >
Q)
{
int N = 100001;
FenwickTree* fenTree = new FenwickTree(N);
for (int i = 0; i < n; i++) {
fenTree->update(arr[i], 1);
}
int x;
for (int i = 0; i < Q.size(); i++) {
if (Q[i].first == 1) {
x = getCount(arr, n,
Q[i].second.first,
Q[i].second.second,
fenTree);
cout << x << " ";
}
else {
setElement(arr, n,
Q[i].second.first,
Q[i].second.second,
fenTree);
}
}
}
// Driver Code
int main()
{
int arr[] = { 1, 2, 2, 3,
4, 4, 5, 6 };
int n = sizeof(arr) / sizeof(arr[0]);
vector > > Q
= { { 1, { 3, 5 } },
{ 1, { 2, 4 } },
{ 1, { 1, 2 } },
{ 2, { 1, 7 } },
{ 1, { 1, 2 } } };
SolveQuery(arr, n, Q);
return 0;
}
4 5 3 2
时间复杂度: O(n*log(N) + Q*log(N))
辅助空间: O(maxm),其中 maxm 是数组中存在的最大元素。
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live