// JavaScript program to calculate sum of
// factorials in an interval and update
// with two types of operations
// Modulus
let MOD = 10000000000;
// Maximum size of input array
let MAX = 100;
// Size for factorial array
let SZ = 40;
let BIT = new Array(MAX + 1).fill(0);
let fact = new Array(SZ + 1).fill(0);
function lower_bound(arr, ele)
{
for (var i = 0; i < arr.length; i++)
{
if (arr[i] >= ele)
return i;
}
return arr.length;
}
// structure for queries with members type,
// leftIndex, rightIndex of the query
class queries
{
constructor(tpe, l, r)
{
this.type = tpe;
this.l = l;
this.r = r;
}
}
// function for updating the value
function update(BIT, x, val, n)
{
while (x <= n)
{
BIT[x] += val;
x += (x & -x);
}
return BIT
}
// function for calculating the required
// sum between two indexes
function summ(x)
{
var s = 0;
while (x > 0)
{
s += BIT[x];
x -= x & -x;
}
return s;
}
// function to return answer to queries
function answerQueries(arr, que, n, q)
{
// Precomputing factorials
fact[0] = 1;
for (var i = 1; i <= 40; i++)
fact[i] = Number((fact[i - 1] * i) % MOD);
// Declaring a Set
var s = new Set();
for (var i = 1; i < n; i++)
{
// inserting indexes of those
// numbers which are lesser
// than 40
if (arr[i] < 40)
{
s.add(i);
BIT = update(BIT, i, fact[arr[i]], n);
}
else
BIT = update(BIT, i, 0, n);
}
for (var i = 0; i < q; i++)
{
// update query of the 1st type
if (que[i].type == 1)
{
while (true)
{
s = Array.from(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 == s.length || 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
BIT = update(BIT, 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.splice(it, 1);
// increment the index
que[i].l += 1;
}
}
// update query of the 2nd type
else if (que[i].type == 2)
{
s = new Set(s);
var idx = que[i].l;
var val = que[i].r;
//update the value to its new value
BIT = update(BIT, 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
console.log((summ(que[i].r) - summ(que[i].l - 1)));
}
}
// Driver Code
let q = 6;
// input array using 1-based indexing
let arr = [0, 1, 2, 1, 4, 5];
let n = arr.length;
// declaring array of structure of type queries
let que = [ new queries(3, 1, 5), new queries(1, 1, 3),
new queries(2, 2, 4),
new queries(3, 2, 4),
new queries(1, 2, 5),
new queries(3, 1, 5) ];
// answer the Queries
answerQueries(arr, que, n, q);
// This code is contributed by phasing17