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 }

 

posted @ 2016-09-24 23:06  Recoder  阅读(639)  评论(0编辑  收藏  举报