给定一个由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 ,请将其从集合中删除,因为即使在进行任何下一次更新查询之后,它也不会影响我们的总和查询答案。
- 对于第二种类型的更新操作,请使用给定值调用更新函数。同样,给定值<40 ,将要替换的元素的索引插入到集合中,如果给定值≥40 ,则将其从集合中删除,因为它在求和查询中不重要。
- 对于第三种类型的总和查询,只需执行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