给定大小为N的数组arr [] ,任务是回答以下类型的Q个查询:
- 1 X 0:在数组后面附加X。
- 2 XY:设置arr [X] = Y。
- 3 X 0:删除arr [X] 。
- 4 XY:在[X,Y]范围内求和。
请注意,删除查询类型3中的arr [X]后,索引X之后的所有元素都将向左移动一个位置。
例子:
Input: arr[] = {1, 2, 5, 3, 4}, Q[][] = {
{4, 2, 4},
{3, 3, 0},
{1, 6, 0},
{4, 3, 5}}
Output:
10
13
First Query -> sum(arr[1], arr[2], arr[3])
Second Query -> arr[] = { 1, 2, 3, 4 }
Third Query -> arr[] = { 1, 2, 3, 4, 6 }
Fourth Query -> sum(arr[2], arr[3], arr[4])
Input: arr[] = {1, 2, 3, 4, 5}, Q[][] = {
{4, 1, 5},
{3, 3, 0},
{1, 6, 0},
{4, 3, 5},
{2, 4, 10}.
{4, 1, 5}}
Output:
15
15
23
天真的方法:解决此问题的天真的方法是直接在给定的数组上执行查询,该数组的时间复杂度为O(Q * N) 。
高效的方法:
- 由于存在一些数据结构,例如分段树或BIT(分域树),它们可以为每个查询提供O(logN)中的点更新和范围总和。
- 那里的帖子使用Fenwick树执行相同的操作,因此强烈建议在Fenwick树中进行点更新。
- 但是主要的问题是执行删除操作(执行第3类查询)后,需要进行移位,这在最坏的情况下会再次导致O(Q * N) 。
- 特技可以使用删除元素之后,只需更新在A [X] = 0的值和索引X之后映射到X之前X +数目的元素被删除。
- 为了找到在X之前删除的元素数量,将使用另一棵fenwick树(在实现中为idx),并在执行删除操作的那个索引处继续加1 。
- 意味着在获取或获取特定索引时,可以查询idx树并将索引X更新为X + sum(X,idx) 。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
// Size of the array (MAX)
const int N = 2e5 + 10;
// To store the sum of
// the array elements
vector bit(N, 0);
// To keep track of how many type 3
// queries have been performed before
// a particular index
vector idx(N, 0);
// Function to perform the point
// update in Fenwick tree
void update(int idx, int val,
vector& bitt)
{
while (idx < N) {
bitt[idx] += val;
idx += idx & (-idx);
}
}
// Function to return the sum
// of the elements A[1...idx]
// from BIT
int sum(int idx,
vector& bitt)
{
int res = 0;
while (idx > 0) {
res += bitt[idx];
idx -= idx & (-idx);
}
return res;
}
// Function to perform the queries and
// return the answer vector
vector peformQueries(vector& A,
vector >& B)
{
// For 1 bases indexing
// insert 0 in the vector
A.insert(A.begin(), 0);
// Updated size of the vector
int n = (int)A.size();
// Updating the bit tree
for (int i = 1; i < n; ++i) {
update(i, A[i], bit);
}
// Vector to store the answers
// of range sum
vector ans;
// Iterating in the query
// vector
for (auto i : B) {
int type = i[0];
int x = i[1], v = i[2];
// If the query is of
// type 1
if (type == 1) {
// Updating the tree
// with x in the last
update(n, x, bit);
// Pushing back the value
// in the original vector
A.push_back(x);
// Incrementing the size
// of the vector by 1
n++;
}
// If the query is of type 2
else if (type == 2) {
// Getting the updated index
// in case of any query of
// type 3 occured before it
int id = x + sum(x, idx);
// Making the effect to that
// value to 0 by subtracting
// same value from the tree
update(id, -A[id], bit);
// Updating the A[id] to v
A[id] = v;
// Now update the
// bit by v at x
update(id, v, bit);
}
// If the query is of type 3
else if (type == 3) {
// Get the current index
int id = x + sum(x, idx);
// Remove the effect of that
// index from the bit tree
update(id, -A[id], bit);
// Update the idx tree
// because one element has
// been deleted
update(x, 1, idx);
// Update the idx val to 0
A[id] = 0;
}
// If the query is of type 4
else {
// Get the updated range
int xx = x + sum(x, idx);
int vv = v + sum(v, idx);
// Push_back the value
ans.push_back(sum(vv, bit)
- sum(xx - 1, bit));
}
}
return ans;
}
// Driver code
int main()
{
vector A = { 1, 2, 5, 3, 4 };
// Queries
vector > B = {
{ 4, 2, 4 },
{ 3, 3, 0 },
{ 1, 6, 0 },
{ 4, 3, 5 },
};
// Get the answer array
vector ans = peformQueries(A, B);
// printing the answer
for (int i : ans)
cout << i << "\n";
return 0;
}
Java
// Java implementation of the approach
import java.util.*;
class GFG {
// Size of the array (MAX)
static int N = (int) 2e5 + 10;
// To store the sum of
// the array elements
static int[] bit = new int[N];
// To keep track of how many type 3
// queries have been performed before
// a particular index
static int[] idx = new int[N];
// Function to perform the point
// update in Fenwick tree
static void update(int idx, int val, int[] bitt) {
while (idx < N) {
bitt[idx] += val;
idx += idx & (-idx);
}
}
// Function to return the sum
// of the elements A[1...idx]
// from BIT
static int sum(int idx, int[] bitt) {
int res = 0;
while (idx > 0) {
res += bitt[idx];
idx -= idx & (-idx);
}
return res;
}
// Function to perform the queries and
// return the answer vector
static Vector peformQueries(Vector A, int[][] B) {
// For 1 bases indexing
// insert 0 in the vector
A.insertElementAt(0, 0);
// Updated size of the vector
int n = (int) A.size();
// Updating the bit tree
for (int i = 1; i < n; ++i) {
update(i, A.elementAt(i), bit);
}
// Vector to store the answers
// of range sum
Vector ans = new Vector<>();
// Iterating in the query
// vector
for (int[] i : B) {
int type = i[0];
int x = i[1], v = i[2];
// If the query is of
// type 1
if (type == 1) {
// Updating the tree
// with x in the last
update(n, x, bit);
// Pushing back the value
// in the original vector
A.add(x);
// Incrementing the size
// of the vector by 1
n++;
}
// If the query is of type 2
else if (type == 2) {
// Getting the updated index
// in case of any query of
// type 3 occured before it
int id = x + sum(x, idx);
// Making the effect to that
// value to 0 by subtracting
// same value from the tree
update(id, -A.elementAt(id), bit);
// Updating the A[id] to v
A.set(id, v);
// Now update the
// bit by v at x
update(id, v, bit);
}
// If the query is of type 3
else if (type == 3) {
// Get the current index
int id = x + sum(x, idx);
// Remove the effect of that
// index from the bit tree
update(id, -A.elementAt(id), bit);
// Update the idx tree
// because one element has
// been deleted
update(x, 1, idx);
// Update the idx val to 0
A.set(id, 0);
}
// If the query is of type 4
else {
// Get the updated range
int xx = x + sum(x, idx);
int vv = v + sum(v, idx);
// Push_back the value
ans.add(sum(vv, bit) - sum(xx - 1, bit));
}
}
return ans;
}
// Driver Code
public static void main(String[] args) {
Integer[] a = { 1, 2, 5, 3, 4 };
Vector A = new Vector(Arrays.asList(a));
// Queries
int[][] B = { { 4, 2, 4 }, { 3, 3, 0 }, { 1, 6, 0 }, { 4, 3, 5 } };
// Get the answer array
Vector ans = peformQueries(A, B);
// printing the answer
for (int i : ans)
System.out.println(i);
}
}
// This code is contributed by
// sanjeev2552
Python3
# Python implementation of the approach
# Size of the array (MAX)
N = int(2e5) + 10
# To store the sum of
# the array elements
bit = [0] * N
# To keep track of how many type 3
# queries have been performed before
# a particular index
idx = [0] * N
# Function to perform the point
# update in Fenwick tree
def update(index: int, val: int, bitt: list):
while index < N:
bitt[index] += val
index += index & -index
# Function to return the sum
# of the elements A[1...idx]
# from BIT
def summation(index: int, bitt: list) -> int:
res = 0
while index > 0:
res += bitt[index]
index -= index & -index
return res
# Function to perform the queries and
# return the answer vector
def performQueries(A: list, B: list) -> list:
global bit, idx
# For 1 bases indexing
# insert 0 in the vector
A.insert(0, 0)
# Updated size of the vector
n = len(A)
# Updating the bit tree
for i in range(1, n):
update(i, A[i], bit)
# Vector to store the answers
# of range sum
ans = []
# Iterating in the query
# vector
for i in B:
type = i[0]
x = i[1]
v = i[2]
# If the query is of
# type 1
if type == 1:
# Updating the tree
# with x in the last
update(n, x, bit)
# Pushing back the value
# in the original vector
A.append(x)
# Incrementing the size
# of the vector by 1
n += 1
# If the query is of type 2
elif type == 2:
# Getting the updated index
# in case of any query of
# type 3 occured before it
id = x + summation(x, idx)
# Making the effect to that
# value to 0 by subtracting
# same value from the tree
update(id, -A[id], bit)
# Updating the A[id] to v
A[id] = v
# Now update the
# bit by v at x
update(id, v, bit)
# If the query is of type 3
elif type == 3:
# Get the current index
id = x + summation(x, idx)
# Remove the effect of that
# index from the bit tree
update(id, -A[id], bit)
# Update the idx tree
# because one element has
# been deleted
update(x, 1, idx)
# Update the idx val to 0
A[id] = 0
# If the query is of type 4
else:
# Get the updated range
xx = x + summation(x, idx)
vv = v + summation(v, idx)
# Push_back the value
ans.append(summation(vv, bit) - summation(xx - 1, bit))
return ans
# Driver Code
if __name__ == "__main__":
A = [1, 2, 5, 3, 4]
# Queries
B = [[4, 2, 4], [3, 3, 0], [1, 6, 0], [4, 3, 5]]
# Get the answer array
ans = performQueries(A, B)
# printing the answer
for i in ans:
print(i)
# This code is contributed by
# sanjeev2552
输出:
10
13
时间复杂度: O(Q * logN + NlogN)