给定一个由N个整数组成的数组A和查询数量Q。您必须回答两种查询。
- 更新[l,r] –对于从l到r的每个i ,使用sqrt(A i )更新A i ,其中sqrt(A i )表示整数形式的A i的平方根。
- 查询[l,r] –计算数组A中介于l和r之间的所有数字的总和。
先决条件:二叉索引树|段树
例子:
Input: A[] = { 4, 5, 1, 2, 4 }, Q = {{2, 1, 5}, {1, 1, 2}, {1, 2, 4}, {2, 1, 5}}
Output: 16
9
Considering 1-based indexing, first query is to calculate sum of numbers from A1 to A5
which is 4 + 5 + 1 + 2 + 4 = 16.
Second query is to update A1 to A2 with its square root. Now, array becomes A[] = { 2, 2, 1, 2, 4 }.
Similarly, third query is to update A2 to A4 with its square root. Now, array becomes A[] = { 2, 1, 1, 1, 4 }.
Fourth query is to calculate sum of numbers from A1 to A5 which is 2 + 1 + 1 + 1 + 4 = 9.
Input: A[] = { 4, 9, 25, 36 }, Q = {{1, 2, 4}, {2, 1, 4}}
Output: 18
天真的方法:一个简单的解决方案是从l到r循环运行,并计算给定范围内的元素总和。要更新值,只需将arr [i]替换为其平方根,即arr [i] = sqrt [arr [i]]即可。
高效的方法:想法是减少每个查询的时间复杂度,并将操作更新为O(logN) 。使用二进制索引树(BIT)或段树。构造一个BIT []数组,并具有两个用于查询和更新操作的函数。现在,对于每个更新操作,关键的观察结果是数字1的平方根将为1 ,因此,如果它存在于更新查询的范围内,则不需要对其进行更新。我们将使用一套只存储那些大于1,并且使用二进制搜索来查找更新查询的L索引,直到每一个元素都在更新查询的范围更新递增L索引号的索引。如果arr [i]的平方根为1 ,则在对其进行更新后,将其从集合中删除,因为即使在进行任何下一次更新查询后,它也始终为1。对于总和查询操作,只需执行query(r)– query(l – 1)即可。
下面是上述方法的实现:
CPP
// CPP program to calculate sum
// in an interval and update with
// square root
#include
using namespace std;
// Maximum size of input array
const int MAX = 100;
int BIT[MAX + 1];
// structure for queries with members type,
// leftIndex, rightIndex of the query
struct queries {
int type, l, r;
};
// function for updating the value
void update(int x, int val, int n)
{
for (x; x <= n; x += x & -x) {
BIT[x] += val;
}
}
// function for calculating the required
// sum between two indexes
int sum(int x)
{
int s = 0;
for (x; x > 0; x -= x & -x) {
s += BIT[x];
}
return s;
}
// function to return answer to queries
void answerQueries(int arr[], queries que[], int n, int q)
{
// Declaring a Set
set s;
for (int i = 1; i < n; i++) {
// inserting indexes of those numbers
// which are greater than 1
if (arr[i] > 1)
s.insert(i);
update(i, arr[i], n);
}
for (int i = 0; i < q; i++) {
// update query
if (que[i].type == 1) {
while (true) {
// find the left index of query in
// the set using binary search
auto it = s.lower_bound(que[i].l);
// if it crosses the right index of
// query or end of set, then break
if (it == s.end() || *it > que[i].r)
break;
que[i].l = *it;
// update the value of arr[i] to
// its square root
update(*it, (int)sqrt(arr[*it]) - arr[*it], n);
arr[*it] = (int)sqrt(arr[*it]);
// if updated value becomes equal to 1
// remove it from the set
if (arr[*it] == 1)
s.erase(*it);
// increment the index
que[i].l++;
}
}
// sum query
else {
cout << (sum(que[i].r) - sum(que[i].l - 1)) << endl;
}
}
}
// Driver Code
int main()
{
int q = 4;
// input array using 1-based indexing
int arr[] = { 0, 4, 5, 1, 2, 4 };
int n = sizeof(arr) / sizeof(arr[0]);
// declaring array of structure of type queries
queries que[q + 1];
que[0].type = 2, que[0].l = 1, que[0].r = 5;
que[1].type = 1, que[1].l = 1, que[1].r = 2;
que[2].type = 1, que[2].l = 2, que[2].r = 4;
que[3].type = 2, que[3].l = 1, que[3].r = 5;
// answer the Queries
answerQueries(arr, que, n, q);
return 0;
}
Python3
# Python program to calculate sum
# in an interval and update with
# square root
from typing import List
import bisect
from math import sqrt, floor
# Maximum size of input array
MAX = 100
BIT = [0 for _ in range(MAX + 1)]
# structure for queries with members type,
# leftIndex, rightIndex of the query
class queries:
def __init__(self, type: int = 0, l: int = 0, r: int = 0) -> None:
self.type = type
self.l = l
self.r = r
# function for updating the value
def update(x: int, val: int, n: int) -> None:
a = x
while a <= n:
BIT[a] += val
a += a & -a
# function for calculating the required
# sum between two indexes
def sum(x: int) -> int:
s = 0
a = x
while a:
s += BIT[a]
a -= a & -a
return s
# function to return answer to queries
def answerQueries(arr: List[int], que: List[queries], n: int, q: int) -> None:
# Declaring a Set
s = set()
for i in range(1, n):
# inserting indexes of those numbers
# which are greater than 1
if (arr[i] > 1):
s.add(i)
update(i, arr[i], n)
for i in range(q):
# update query
if (que[i].type == 1):
while True:
ss = list(sorted(s))
# find the left index of query in
# the set using binary search
# auto it = s.lower_bound(que[i].l);
it = bisect.bisect_left(ss, que[i].l)
# if it crosses the right index of
# query or end of set, then break
if it == len(s) or ss[it] > que[i].r:
break
que[i].l = ss[it]
# update the value of arr[i] to
# itss square root
update(ss[it], floor(sqrt(arr[ss[it]]) - arr[ss[it]]), n)
arr[ss[it]] = floor(sqrt(arr[ss[it]]))
# if updated value becomes equal to 1
# remove it from the set
if (arr[ss[it]] == 1):
s.remove(ss[it])
# increment the index
que[i].l += 1
# sum query
else:
print(sum(que[i].r) - sum(que[i].l - 1))
# Driver Code
if __name__ == "__main__":
q = 4
# input array using 1-based indexing
arr = [0, 4, 5, 1, 2, 4]
n = len(arr)
# declaring array of structure of type queries
que = [queries() for _ in range(q + 1)]
que[0].type, que[0].l, que[0].r = 2, 1, 5
que[1].type, que[1].l, que[1].r = 1, 1, 2
que[2].type, que[2].l, que[2].r = 1, 2, 4
que[3].type, que[3].l, que[3].r = 2, 1, 5
# answer the Queries
answerQueries(arr, que, n, q)
# This code is contributed by sanjeev2552
16
9