📜  范围总和查询和平方根更新

📅  最后修改于: 2021-04-17 11:12:54             🧑  作者: Mango

给定一个由N个整数组成的数组A和查询数量Q。您必须回答两种查询。

  • 更新[l,r] –对于从lr的每个i ,使用sqrt(A i )更新A i ,其中sqrt(A i )表示整数形式的A i的平方根。
  • 查询[l,r] –计算数组A中介于lr之间的所有数字的总和。

先决条件:二叉索引树|段树
例子:

天真的方法:一个简单的解决方案是从lr循环运行,并计算给定范围内的元素总和。要更新值,只需将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