Explanation
Firstly, a note on notation: let denote the th Fibonacci number. That is,
In this problem, we will build a segment tree over the array. For a leaf node in the segment tree with value , we will store a pair of values . 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 has children and , then .
We will use the term cycle by k to denote transforming some pair to . By default, the term cycle refers to cycle by 1.
For each update, we need to cycle each leaf node by some amount such that the value in a node affected goes from to . We can do this using matrix exponentiation.
First note that for a matrix , we can cycle it by multiplying by . That is,
Inductively, we can cycle by by multiplying multiple times:
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 is a one-by-two matrix for , then the following property is satisfied:
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 secondusing 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!