HDU 5068 Harry And Math Teacher 线段树+矩阵乘法

题意:

  一栋楼有n层,每一层有2个门,每层的两个门和下一层之间的两个门之间各有一条路(共4条)。

  有两种操作:

  0 x y : 输出第x层到第y层的路径数量。

  1 x y z : 改变第x层 的 y门 到第x+1层的 z门的通断情况。

思路:

  门之间的路径数可以用矩阵来表示,经过的中间层可以用矩阵乘积表示。 所以用线段树维护矩阵乘积即可。

代码:

  

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <cmath>
  6 #include <algorithm>
  7 #include <string>
  8 #include <queue>
  9 #include <stack>
 10 #include <vector>
 11 #include <map>
 12 #include <set>
 13 #include <functional>
 14 #include <cctype>
 15 #include <time.h>
 16 
 17 using namespace std;
 18 
 19 typedef __int64 ll;
 20 
 21 const int INF = 1<<30;
 22 const int MAXN = 5e4+55;
 23 const ll MOD = 1e9+7;
 24 
 25 struct Matrix {
 26     ll a[2][2];
 27 
 28     Matrix() {}
 29 
 30     Matrix(int x) {
 31         for (int i = 0; i < 2; i++)
 32             for (int j = 0; j < 2; j++)
 33                 a[i][j] = i==j ? x : 0;
 34     }
 35 
 36     Matrix operator * (const Matrix &x) {
 37         Matrix res;
 38         for (int i = 0; i < 2; i ++) {
 39             for (int j = 0; j < 2; j++) {
 40                 res.a[i][j] = 0;
 41                 for (int k = 0; k < 2; k++) {
 42                     res.a[i][j] = (res.a[i][j]+a[i][k]*x.a[k][j])%MOD;
 43                 }
 44             }
 45         }
 46         return res;
 47     }
 48 
 49     inline ll sum() {
 50         return (a[0][0] + a[0][1] + a[1][0] + a[1][1])%MOD;
 51     }
 52 
 53     inline void update(int i, int j) {
 54         a[i][j] ^= 1;
 55     }
 56 
 57     inline void init() {
 58         a[0][0] = a[0][1] = a[1][0] = a[1][1] = 1;
 59     }
 60     void output() {
 61         puts("Matrix: ");
 62         for (int i = 0; i < 2; i ++) {
 63             for (int j = 0; j < 2; j++)
 64                 printf("%I64d ", a[i][j]);
 65             puts("");
 66         }
 67     }
 68 };
 69 
 70 Matrix a[MAXN<<2];
 71 int id[MAXN];
 72 
 73 #define LS l, m, p<<1
 74 #define RS m+1, r, p<<1|1
 75 
 76 inline void pushUp(int p) {
 77     a[p] = a[p<<1]*a[p<<1|1];
 78 }
 79 
 80 void build(int l, int r, int p) {
 81     if (l==r) {
 82         a[p].init();
 83         id[l] = p;
 84         return ;
 85     }
 86     int m = (l+r) >> 1;
 87     build(LS);
 88     build(RS);
 89     pushUp(p);
 90 }
 91 
 92 void update(int p, int i, int j) {
 93     p = id[p];
 94     a[p].update(i, j);
 95     p >>= 1;
 96     while (p>0) {
 97         pushUp(p);
 98         p >>= 1;
 99     }
100 }
101 
102 Matrix query(int L, int R, int l, int r, int p) {
103     if (L<=l&&r<=R)
104         return a[p];
105 
106     int m = (l+r)>>1;
107 
108     Matrix res(1);
109     if (L<=m) res = res * query(L, R, LS);
110     if (m <R) res = res * query(L, R, RS);
111 
112     return res;
113 }
114 
115 int main() {
116     #ifdef Phantom01
117         freopen("1003.txt", "r", stdin);
118     #endif //Phantom01
119 
120     int n, m;
121     int op, x, y, z;
122     while (scanf("%d%d", &n, &m)!=EOF) {
123         n--;
124         build(1, n, 1);
125         while (m--) {
126             scanf("%d", &op);
127             if (op==0) {
128                 scanf("%d%d", &x, &y);
129                 y--;
130                 printf("%I64d
", query(x, y, 1, n, 1).sum());
131             } else {
132                 scanf("%d%d%d", &x, &y, &z);
133                 y--; z--;
134                 update(x, y, z);
135             }
136         }
137     }
138 
139     return 0;
140 }
View Code
原文地址:https://www.cnblogs.com/Phantom01/p/4054945.html