Title:
There are \ (n \) floors, each floor has two stairs (No. \ (0 \) and \ (1 \). At the beginning, the stairs of the \ (i \) floor and the \ (i +1 \) floor can reach two.
There are several operations:
- Reverse the connectivity of stairs \ (x \) on level \ (i \) and \ (y \) on level \ (i + 1 \)
- Query the number of schemes from layer \ (x \) to layer \ (y \).
Train of thought:
Use \ (a {x, y} \) to represent the scheme number of \ (x \) stairs from \ (i \) layer to \ (Y \) stairs from \ (i + 1 \) layer.
So obviously, all \ (a {x, y} = 1 \) at the beginning.
Use \ (f {i, X} \) to indicate the number of schemes to reach the stairs \ (x \) on the \ (i \) floor.
With transfer matrix:
\[
\begin{eqnarray*}
\left[
\begin{array} {cccc}
f_{i, 0}\quad f_{i, 1}
\end{array}
\right]
\left[
\begin{array}{cccc}
a_{0, 0} \quad a_{1, 0} \\
a_{0, 1} \quad a_{1, 1}
\end{array}
\right]
=
\left[
\begin{array}{cccc}
f_{i + 1, 0} \quad f_{i + 1, 1}
\end{array}
\right]
\end{eqnarray*}
\]
Then put the matrix into the line tree.
In fact, we can think of it as follows:
Use \ (f {i, j, x, y} \) to represent the number of schemes from \ (x \) of \ (i \) to \ (Y \) of \ (j \) layer.
Then there are:
\[
\begin{eqnarray*}
\left[
\begin{array}{cccc}
f_{i, j, 0, 0} \quad f_{i, j, 0, 1} \\
f_{i, j, 1, 0} \quad f_{i, j, 1, 1}
\end{array}
\right]
\left[
\begin{array}{cccc}
f_{j, j + 1, 0, 0} \quad f_{j, j + 1, 0, 1} \\
f_{j, j + 1, 1, 0} \quad f_{j, j + 1, 1, 1}
\end{array}
\right]
=
\left[
\begin{array}{cccc}
f_{i, j + 1, 0, 0} \quad f_{i, j + 1, 0, 1} \\
f_{i, j + 1, 1, 0} \quad f_{i, j + 1, 1, 1}
\end{array}
\right]
\end{eqnarray*}
\]
It seems to be more convenient.
Code:
#include <bits/stdc++.h> using namespace std; #define ll long long #define N 50010 const ll p = 1e9 + 7; int n, q; void add(ll &x, ll y) { x += y; if (x >= p) x -= p; } struct SEG { struct node { ll a[2][2]; node() { memset(a, 0, sizeof a); } node operator * (const node &other) const { node res = node(); for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { for (int k = 0; k < 2; ++k) { add(res.a[i][j], a[i][k] * other.a[k][j] % p); } } } return res; } }t[N << 2], res; void build(int id, int l, int r) { if (l == r) { for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { t[id].a[i][j] = 1; } } return; } int mid = (l + r) >> 1; build(id << 1, l, mid); build(id << 1 | 1, mid + 1, r); t[id] = t[id << 1] * t[id << 1 | 1]; } void update(int id, int l, int r, int pos, int x, int y) { if (l == r) { t[id].a[x - 1][y - 1] ^= 1; return; } int mid = (l + r) >> 1; if (pos <= mid) update(id << 1, l, mid, pos, x, y); else update(id << 1 | 1, mid + 1, r, pos, x, y); t[id] = t[id << 1] * t[id << 1 | 1]; } node query(int id, int l, int r, int ql, int qr) { if (l >= ql && r <= qr) { return t[id]; } int mid = (l + r) >> 1; if (ql <= mid && qr > mid) { return query(id << 1, l, mid, ql, qr) * query(id << 1 | 1, mid + 1, r, ql, qr); } else if (ql <= mid) { return query(id << 1, l, mid, ql, qr); } else if (qr > mid) { return query(id << 1 | 1, mid + 1, r, ql, qr); } else { assert(0); } } }seg; int main() { while (scanf("%d%d", &n, &q) != EOF) { seg.build(1, 1, n); int op, x, y, z; ll res; while (q--) { scanf("%d%d%d", &op, &x, &y); switch(op) { case 0 : seg.res = seg.query(1, 1, n, x, y - 1); res = 0; for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { add(res, seg.res.a[i][j]); } } printf("%lld\n", res); break; case 1 : scanf("%d", &z); seg.update(1, 1, n, x, y, z); break; } } } return 0; }