Editorial For Series-Sum-1 in Algos-Inductions-Round-1: O (N Q) L, R N

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 3

Editorial for Series-Sum-1 in Algos-inductions-round-1

Concept involved : Partial Sum.

The steps involved in the naive approach to solve this question is,

1. Pre-process the recursive function f using f[i] = 3*f[i-2] + 4*f[i-1] in O(n).


2. For each query l, r , iterate through the array x and increment the value if x[i] by f[i-l+1].
3. Print the array x.

The time complexity of this method is O(n*q), as for each query, the range given by l, r can be n.

As, you might have guessed, this method will work fine for the initial test-cases. But for it to satisfy
bigger test cases, we need a better algorithm.

I saw a lot of people writing the following function for finding f[i]

int f1, f2;


int func(int i) {
if(i == 1)
return f1;
else if(f == 2)
return f2;

return 3*func(i-2) + 4*func(i-1);


}

This function takes exponential time to compute value of f[i] as the same values are going to be
passed again and again. So, a better is fairly simple. Run a for loop to calclate the value of f[i] and
store it in an array.

Solving this question using partial sum method.

1. Pre-process the recursive function f using f[i] = 3*f[i-2] + 4*f[i-1] in O(n).


2. For each query l, r , instead of incrementing the whole range, we will be incrementing only the
required terms from which we can calculate the remaining terms at the end of all queries.
3. Since every term depends on two of its immediate previous terms, we will be needing to store
the values for l, l+1, from which we can calculate the remaining terms by the formula x[l+2] =
3*x[l] + 4*x[l+1] and so on. To terminate this addition process, we need to nullify this
sequence from the term x[r+1].
4. Before nullifying x[r+1], there will be an excess value of f[r-l+2] in x[r+1], So, we will be
subtracting f[r-l+2] from x[r+1].
5. Similarly, after nullifying x[r+1], x[r+2] will have an excess value of 3*f[r-l] from f[r-l+2] =
3*f[r-l] + 4*f[r-l+1]. It doesn't have the term 4*f[r-l+1] because, we have already nullified
it's effect in the previous term. So, we need to subtract 3*f[r-l] from x[r+2].
6. After all queries, we can fill the terms in array x by the formula, x[i] = 3*x[i-2] + 4*x[i-1].
7. Similar approach can be divised for the cases where l == r.

The source code for this arroach is given below. Do ask if you find any difficulty in understand any
part. In the code, the array p is used instead of x. Too lazy to change :p.
#include <bits/stdc++.h>

#define rep(i, a, b) for(i=a; i<=b; i++)


#define rrep(i, a, b) for(i=a; i>=b; i--)
#define all(x) x.begin(),x.end()
#define pb push_back
#define xx first
#define yy second
#define mp make_pair
#define st string
#define vi vector<int>
#define vs vector<st>
#define mii map<int,int>
#define pii pair<int,int>
#define vpii vector<pii>

typedef long long ll;


typedef unsigned long long ull;

using namespace std;

const long long mod = 1000000007;

int main() {
ll n, q;
cin>>n>>q;

ll f[n + 2];
cin>>f[0]>>f[1];

ll a, b, i;

a = 3; b = 4;
rep(i, 2, n+1) {
f[i] = ((a * f[i-2]) % mod + (b * f[i-1]) % mod) % mod;
}

ll p[n + 2] = {0};

while(q--) {
ll l, r;
cin>>l>>r;
l--; r--;

if(l < r) {
p[l] = (p[l] + f[0]) % mod;
p[l + 1] = (((p[l + 1] + f[1]) % mod) + mod - ((b * f[0]) % mod)) % mod;

p[r + 1] = (p[r + 1] + mod - f[r - l + 1]) % mod;


p[r + 2] = (p[r + 2] + mod - ((a * f[r - l]) % mod)) % mod;
}
else {
p[l] = (p[l] + f[0]) % mod;
p[l + 1] = (p[l + 1] + mod - ((b * f[0]) % mod)) % mod;
p[l + 2] = (p[l + 2] + mod - ((a * f[0]) % mod)) % mod;
}
}
rep(i, 0, n-1) {
if(i > 1)
p[i] = (p[i] + ((a * p[i - 2]) % mod)) % mod;
if(i)
p[i] = (p[i] + ((b * p[i - 1]) % mod)) % mod;

cout<<p[i]<<" ";
}

return 0;
}

You might also like