给定一个由N 个整数组成的数组arr[]和查询数量Q 。任务是回答三种类型的查询。
- 更新 [l, r] – 对于范围[l, r] 中的每个i 将arr[i]增加1 。
- 更新 [l, val] – 将arr[l]的值更改为val 。
- 查询 [l, r] – 计算arr[i]! % 10 9对于[l, r]范围内的所有i ,其中arr[i]!是arr[i]的阶乘。
先决条件:二叉索引树 |段树
例子:
Input: Q = 6, arr[] = { 1, 2, 1, 4, 5 }
3 1 5
1 1 3
2 2 4
3 2 4
1 2 5
3 1 5
Output:
148
50
968
1st query, the required sum is (1! + 2! + 1! + 4! + 5!) % 109 = 148
2nd query, the array becomes arr[] = { 2, 3, 2, 4, 5 }
3rd query, array becomes arr[] = { 2, 4, 2, 4, 5 }
4th query, the required sum is (4! + 2! + 4!) % 109 = 50
5th query, the array becomes arr[] = { 2, 5, 3, 5, 6 }
6th query, the required sum is (2! + 5! + 3! + 5! + 6!) % 109 = 968
朴素的方法:一个简单的解决方案是运行从l到r的循环,并为第三个查询计算给定范围内元素阶乘的总和(预先计算)。对于第二个查询,要更新值,只需将arr[i]替换为给定值,即arr[i] = val 。对于第一种类型的查询,增加arr[i]的值,即arr[i] = arr[i] + 1 。
高效方法:仔细分析可以看出, 40!可以被 10 9整除,这意味着每个大于40 的数的阶乘都可以被10 9整除。因此,这在我们对第三个查询的答案中增加了零。这个想法是将每个查询和更新操作的时间复杂度降低到O(logN) 。使用二叉索引树 (BIT) 或段树。构造一个BIT[]数组,有查询和更新操作两个函数。
- 现在,对于第一种类型的每个更新操作,关键观察是给定范围内的数字最多可以更新为40 ,因为在那之后就无关紧要了,因为它将在我们的最终答案中添加零。我们将使用一个集合来存储那些小于 10 的数字的索引,并使用二进制搜索来查找更新查询的 l 索引并递增 l 索引,直到每个元素都在该更新查询的范围内更新。如果arr[i]在增加1后变得大于或等于40 ,请将其从集合中删除,因为即使在任何下一次更新查询之后它也不会影响我们对 sum 查询的答案。
- 对于第二种类型的更新操作,调用给定值的更新函数。此外,给定值< 40 ,将要替换的元素的索引插入到集合中,如果给定值≥ 40 ,则将其从集合中删除,因为它在 sum 查询中不重要。
- 对于第三种类型的和查询,只需执行query(r) – query(l – 1) 。
下面是上述方法的实现:
C++
// CPP program to calculate sum of
// factorials in an interval and update
// with two types of operations
#include
using namespace std;
// Modulus
const int MOD = 1e9;
// Maximum size of input array
const int MAX = 100;
// Size for factorial array
const int SZ = 40;
int BIT[MAX + 1], fact[SZ + 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)
{
// Precomputing factorials
fact[0] = 1;
for (int i = 1; i < 41; i++)
fact[i] = (fact[i - 1] * i) % MOD;
// Declaring a Set
set s;
for (int i = 1; i < n; i++) {
// inserting indexes of those
// numbers which are lesser
// than 40
if (arr[i] < 40) {
s.insert(i);
update(i, fact[arr[i]], n);
}
else
update(i, 0, n);
}
for (int i = 0; i < q; i++) {
// update query of the 1st type
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;
int val = arr[*it] + 1;
// update the value of arr[i] to
// its new value
update(*it, fact[val] - fact[arr[*it]], n);
arr[*it]++;
// if updated value becomes greater
// than or equal to 40 remove it from
// the set
if (arr[*it] >= 40)
s.erase(*it);
// increment the index
que[i].l++;
}
}
// update query of the 2nd type
else if (que[i].type == 2) {
int idx = que[i].l;
int val = que[i].r;
// update the value to its new value
update(idx, fact[val] - fact[arr[idx]], n);
arr[idx] = val;
// If the value is less than 40, insert
// it into set, otherwise remove it
if (val < 40)
s.insert(idx);
else
s.erase(idx);
}
// sum query of the 3rd type
else
cout << (sum(que[i].r) - sum(que[i].l - 1))
<< endl;
}
}
// Driver Code to test above functions
int main()
{
int q = 6;
// input array using 1-based indexing
int arr[] = { 0, 1, 2, 1, 4, 5 };
int n = sizeof(arr) / sizeof(arr[0]);
// declaring array of structure of type queries
queries que[q + 1];
que[0].type = 3, que[0].l = 1, que[0].r = 5;
que[1].type = 1, que[1].l = 1, que[1].r = 3;
que[2].type = 2, que[2].l = 2, que[2].r = 4;
que[3].type = 3, que[3].l = 2, que[3].r = 4;
que[4].type = 1, que[4].l = 2, que[4].r = 5;
que[5].type = 3, que[5].l = 1, que[5].r = 5;
// answer the Queries
answerQueries(arr, que, n, q);
return 0;
}
Python3
# Python3 program to calculate sum of
# factorials in an interval and update
# with two types of operations
from bisect import bisect_left as lower_bound
# Modulus
MOD = 1e9
# Maximum size of input array
MAX = 100
# Size for factorial array
SZ = 40
BIT = [0] * (MAX + 1)
fact = [0] * (SZ + 1)
# structure for queries with members type,
# leftIndex, rightIndex of the query
class queries:
def __init__(self, tpe, l, r):
self.type = tpe
self.l = l
self.r = r
# function for updating the value
def update(x, val, n):
global BIT
while x <= n:
BIT[x] += val
x += x & -x
# function for calculating the required
# sum between two indexes
def summ(x):
global BIT
s = 0
while x > 0:
s += BIT[x]
x -= x & -x
return s
# function to return answer to queries
def answerQueries(arr: list, que: list,
n: int, q: int):
global fact
# Precomputing factorials
fact[0] = 1
for i in range(1, 41):
fact[i] = int((fact[i - 1] * i) % MOD)
# Declaring a Set
s = set()
for i in range(1, n):
# inserting indexes of those
# numbers which are lesser
# than 40
if arr[i] < 40:
s.add(i)
update(i, fact[arr[i]], n)
else:
update(i, 0, n)
for i in range(q):
# update query of the 1st type
if que[i].type == 1:
while True:
s = list(s)
s.sort()
# find the left index of query in
# the set using binary search
it = lower_bound(s, que[i].l)
# if it crosses the right index of
# query or end of set, then break
if it == len(s) or s[it] > que[i].r:
break
que[i].l = s[it]
val = arr[s[it]] + 1
# update the value of arr[i] to
# its new value
update(s[it], fact[val] -
fact[arr[s[it]]], n)
arr[s[it]] += 1
# if updated value becomes greater
# than or equal to 40 remove it from
# the set
if arr[s[it]] >= 40:
s.remove(it)
# increment the index
que[i].l += 1
# update query of the 2nd type
elif que[i].type == 2:
s = set(s)
idx = que[i].l
val = que[i].r
# update the value to its new value
update(idx, fact[val] - fact[arr[idx]], n)
arr[idx] = val
# If the value is less than 40, insert
# it into set, otherwise remove it
if val < 40:
s.add(idx)
else:
s.remove(idx)
# sum query of the 3rd type
else:
print((summ(que[i].r) -
summ(que[i].l - 1)))
# Driver Code
if __name__ == "__main__":
q = 6
# input array using 1-based indexing
arr = [0, 1, 2, 1, 4, 5]
n = len(arr)
# declaring array of structure of type queries
que = [ queries(3, 1, 5),
queries(1, 1, 3),
queries(2, 2, 4),
queries(3, 2, 4),
queries(1, 2, 5),
queries(3, 1, 5) ]
# answer the Queries
answerQueries(arr, que, n, q)
# This code is contributed by
# sanjeev2552
148
50
968
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。