Codeforces 719 E. Sasha and Array (线段树+矩阵运算)
题目链接:http://codeforces.com/contest/719/problem/E
题意:操作1将[l, r] + x;
操作2求f[l] + ... + f[r];
题解:注意矩阵可以是a*(b + c) = a*b + a*c ,还有update的时候传入矩阵
1 //#pragma comment(linker, "/STACK:102400000, 102400000") 2 #include <algorithm> 3 #include <iostream> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <ctime> 10 #include <list> 11 #include <set> 12 #include <map> 13 using namespace std; 14 typedef long long LL; 15 typedef pair <int, int> P; 16 const int N = 1e5 + 5; 17 LL a[N], mod = 1e9 + 7; 18 struct data { 19 LL mat[3][3]; 20 data() { 21 mat[1][1] = mat[2][1] = mat[1][2] = 1; 22 mat[2][2] = 0; 23 } 24 void init() { 25 mat[1][1] = mat[2][2] = 1; 26 mat[1][2] = mat[2][1] = 0; 27 } 28 }op; 29 struct SegTree { 30 int l, r; 31 data lazy; 32 data val; 33 }T[N << 2]; 34 35 data operator +(const data &a, const data &b) { 36 data ans; 37 for(int i = 1; i <= 2; ++i) { 38 for(int j = 1; j <= 2; ++j) { 39 ans.mat[i][j] = (a.mat[i][j] + b.mat[i][j]) % mod; 40 } 41 } 42 return ans; 43 } 44 45 data operator *(const data &a, const data &b) { 46 data ans; 47 for(int i = 1; i <= 2; ++i) { 48 for(int j = 1; j <= 2; ++j) { 49 ans.mat[i][j] = 0; 50 for(int k = 1; k <= 2; ++k) { 51 ans.mat[i][j] = (ans.mat[i][j] + a.mat[i][k] * b.mat[k][j] % mod) % mod; 52 } 53 } 54 } 55 return ans; 56 } 57 58 data operator ^(data a, LL n) { 59 data ans; 60 for(int i = 1; i <= 2; ++i) { 61 for(int j = 1; j <= 2; ++j) { 62 ans.mat[i][j] = (i == j); 63 } 64 } 65 while(n) { 66 if(n & 1) 67 ans = ans * a; 68 a = a * a; 69 n >>= 1; 70 } 71 return ans; 72 } 73 74 bool cmp(const data &a) { 75 for(int i = 1; i <= 2; ++i) { 76 for(int j = 1; j <= 2; ++j) { 77 if(a.mat[i][j] != op.mat[i][j]) 78 return false; 79 } 80 } 81 return true; 82 } 83 84 inline void pushdown(int p) { 85 if(!cmp(T[p].lazy)) { 86 T[p << 1].lazy = T[p].lazy * T[p << 1].lazy; 87 T[(p << 1)|1].lazy = T[p].lazy * T[(p << 1)|1].lazy; 88 T[p << 1].val = T[p << 1].val * T[p].lazy; 89 T[(p << 1)|1].val = T[(p << 1)|1].val * T[p].lazy; 90 T[p].lazy.init(); 91 } 92 } 93 94 void build(int p, int l, int r) { 95 int mid = (l + r) >> 1; 96 T[p].l = l, T[p].r = r, T[p].lazy.init(); 97 if(l == r) { 98 scanf("%lld", a + l); 99 T[p].val = T[p].val ^ (a[l] - 1); 100 return ; 101 } 102 build(p << 1, l, mid); 103 build((p << 1)|1, mid + 1, r); 104 T[p].val = T[p << 1].val + T[(p << 1)|1].val; 105 } 106 107 void update(int p, int l, int r, data add) { 108 int mid = (T[p].l + T[p].r) >> 1; 109 if(T[p].l == l && T[p].r == r) { 110 T[p].lazy = add * T[p].lazy; 111 T[p].val = T[p].val * add; 112 return ; 113 } 114 pushdown(p); 115 if(r <= mid) { 116 update(p << 1, l, r, add); 117 } else if(l > mid) { 118 update((p << 1)|1, l, r, add); 119 } else { 120 update(p << 1, l, mid, add); 121 update((p << 1)|1, mid + 1, r, add); 122 } 123 T[p].val = T[p << 1].val + T[(p << 1)|1].val; 124 } 125 126 LL query(int p, int l, int r) { 127 int mid = (T[p].l + T[p].r) >> 1; 128 if(T[p].l == l && T[p].r == r) { 129 return T[p].val.mat[1][1]; 130 } 131 pushdown(p); 132 if(r <= mid) { 133 return query(p << 1, l, r); 134 } else if(l > mid) { 135 return query((p << 1)|1, l, r); 136 } else { 137 return (query(p << 1, l, mid) + query((p << 1)|1, mid + 1, r)) % mod; 138 } 139 } 140 141 int main() 142 { 143 op.init(); 144 int n, m; 145 scanf("%d %d", &n, &m); 146 build(1, 1, n); 147 int c, l, r; 148 LL add; 149 while(m--) { 150 scanf("%d %d %d", &c, &l, &r); 151 if(c == 1) { 152 scanf("%lld", &add); 153 data temp; 154 update(1, l, r, temp ^ add); 155 } else { 156 printf("%lld\n", query(1, l, r)); 157 } 158 } 159 return 0; 160 }