Table of Contents

ExplanationImplementation

Explanation

Firstly, a note on notation: let FiF_i denote the iith Fibonacci number. That is,

Fi={0i=01i=1Fi1+Fi2i2F_i = \begin{cases} 0 & i = 0 \\ 1 & i = 1 \\ F_{i - 1} + F_{i - 2} & i \geq 2 \\ \end{cases}

In this problem, we will build a segment tree over the array. For a leaf node in the segment tree with value vv, we will store a pair of values (Fv1,Fv)(F_{v - 1}, F_v). For all non-leaf nodes, we will store a pair of values equal to the pair-sum of its children. That is, if a node uu has children vv and ww, then u=(v0+w0,v1+w1)u = (v_0 + w_0, v_1 + w_1).

We will use the term cycle by k to denote transforming some pair (Fi1,Fi)(F_{i - 1}, F_i) to (Fi1+k,Fi+k)(F_{i - 1 + k}, F_{i + k}). By default, the term cycle refers to cycle by 1.

For each update, we need to cycle each leaf node by some amount xx such that the value in a node affected goes from (Fv1,Fv)(F_{v - 1}, F_v) to (Fv1+x,Fv+x)(F_{v - 1 + x}, F_{v + x}). We can do this using matrix exponentiation.

First note that for a matrix (Fi1Fi)\begin{pmatrix} F_{i - 1} & F_i \end{pmatrix}, we can cycle it by multiplying by (0111)\begin{pmatrix} 0 & 1 \\ 1 & 1 \end{pmatrix}. That is,

(FiFi+1)=(Fi1Fi)(0111)\begin{pmatrix} F_i & F_{i + 1} \end{pmatrix} = \begin{pmatrix} F_{i - 1} & F_i \end{pmatrix}\begin{pmatrix} 0 & 1 \\ 1 & 1 \end{pmatrix}

Inductively, we can cycle by kk by multiplying multiple times:

(Fi1+kFi+k)=(Fi1Fi)(0111)k\begin{pmatrix} F_{i - 1 + k} & F_{i + k} \end{pmatrix} = \begin{pmatrix} F_{i - 1} & F_i \end{pmatrix}\begin{pmatrix} 0 & 1 \\ 1 & 1 \end{pmatrix}^k

We can use binary exponentiation to quickly compute powers of the two-by-two matrix.

Secondly, we need to utilize the distributive property of matrix multiplication to same-size matrices. That is, if mkm_k is a one-by-two matrix for k[1,n]k \in [1, n], then the following property is satisfied:

(m1+m2++mn)(0111)=m1(0111)+m2(0111)++mn(0111)(m_1 + m_2 + \dots + m_n) \cdot \begin{pmatrix} 0 & 1 \\ 1 & 1 \end{pmatrix} = m_1 \cdot \begin{pmatrix} 0 & 1 \\ 1 & 1 \end{pmatrix} + m_2 \cdot \begin{pmatrix} 0 & 1 \\ 1 & 1 \end{pmatrix} + \dots + m_n \cdot \begin{pmatrix} 0 & 1 \\ 1 & 1 \end{pmatrix}

In that way, we can utilize lazy propagation on the segment tree. We will store an integer tag in each node denoting the lazy update, which denotes that we must cycle every node in its subtree by the value of the tag. When propagating, we can simply update the node by binary exponentiating and then multiplying, then storing it in the lazy tag. Querying works as normal on the segment tree.

Implementation

C++

#include <bits/stdc++.h>
using namespace std;
#define f first
#define s second
using ll = long long;
using pll = pair<ll, ll>;
const int MAXN = 1e5 + 1;

Join the USACO Forum!

Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!