Codeforces Round #373 (Div. 1) C. Sasha and Array 線段樹

林堯彬發表於2020-04-04

連結:

http://codeforces.com/contest/718/problem/C

題意:

維護一個長度為n的數列a,支援下面兩個操作: 

1 l r x — increase all integers on the segment from l to r by values x;

2 l r — find , where f(x) is the x-th Fibonacci number. As this number may be large, you only have to find it modulo 109 + 7.

題解:

斐波那契可以有矩陣快速冪求得,所以我們的線段樹的每個節點都是一個2*2的矩陣,

父親節點就是兒子節點的和,兒子同時+x也就是父親*(A^x)次方,因為矩陣滿足分配律

這樣就能用線段樹來寫了

程式碼:

 31 struct Matrix {
 32     int a[2][2];
 33     Matrix() {
 34         memset(a, 0, sizeof(a));
 35     }
 36     void init() {
 37         rep(i, 0, 2) rep(j, 0, 2)
 38             a[i][j] = (i == j);
 39     }
 40     Matrix operator+(const Matrix &B)const {
 41         Matrix C;
 42         rep(i, 0, 2) rep(j, 0, 2)
 43             C.a[i][j] = (a[i][j] + B.a[i][j]) % MOD;
 44         return C;
 45     }
 46     Matrix operator*(const Matrix &B)const {
 47         Matrix C;
 48         rep(i, 0, 2) rep(k, 0, 2) rep(j, 0, 2)
 49             C.a[i][j] = (C.a[i][j] + 1LL * a[i][k] * B.a[k][j]) % MOD;
 50         return C;
 51     }
 52     Matrix operator^(const int &n)const {
 53         Matrix A = *this, res;
 54         res.init();
 55         int p = n;
 56         while (p) {
 57             if (p & 1) res = res*A;
 58             A = A*A;
 59             p >>= 1;
 60         }
 61         return res;
 62     }
 63 };
 64 
 65 int n, m;
 66 int a[MAXN];
 67 Matrix A, Tree[MAXN<<2], Lazy[MAXN<<2];
 68 
 69 void pushup(int rt) {
 70     Tree[rt] = Tree[rt << 1] + Tree[rt << 1 | 1];
 71 }
 72 
 73 void pushdown(int rt) {
 74     Tree[rt << 1] = Lazy[rt] * Tree[rt << 1];
 75     Tree[rt << 1 | 1] = Lazy[rt] * Tree[rt << 1 | 1];
 76     Lazy[rt << 1] = Lazy[rt] * Lazy[rt << 1];
 77     Lazy[rt << 1 | 1] = Lazy[rt] * Lazy[rt << 1 | 1];
 78     Lazy[rt].init();
 79 }
 80 
 81 void build(int l,int r,int rt){
 82     Lazy[rt].init();
 83     if (l == r) {
 84         Tree[rt] = A^a[l];
 85         return;
 86     }
 87     int m = (l + r) >> 1;
 88     build(lson);
 89     build(rson);
 90     pushup(rt);
 91 }
 92 
 93 void update(int L, int R, Matrix x, int l, int r, int rt) {
 94     if (L <= l && r <= R) {
 95         Tree[rt] = Tree[rt] * x;
 96         Lazy[rt] = Lazy[rt] * x;
 97         return;
 98     }
 99     pushdown(rt);
100     int m = (l + r) >> 1;
101     if (L <= m) update(L, R, x, lson);
102     if (R > m) update(L, R, x, rson);
103     pushup(rt);
104 }
105 
106 int query(int L, int R, int l, int r, int rt) {
107     if (L <= l && r <= R) return Tree[rt].a[1][0];
108     pushdown(rt);
109     int m = (l + r) >> 1;
110     int res = 0;
111     if (L <= m) res = (res + query(L, R, lson)) % MOD;
112     if (R > m) res = (res + query(L, R, rson)) % MOD;
113     return res;
114 }
115 
116 int main() {
117     ios::sync_with_stdio(false), cin.tie(0);
118     A.a[0][0] = 1, A.a[0][1] = 1;
119     A.a[1][0] = 1, A.a[1][1] = 0;
120     cin >> n >> m;
121     rep(i, 1, n + 1) cin >> a[i];
122     build(1, n, 1);
123     while (m--) {
124         int tp, l, r, x;
125         cin >> tp >> l >> r;
126         if (tp == 1) {
127             cin >> x;
128             update(l, r, A^x, 1, n, 1);
129         }
130         else cout << query(l, r, 1, n, 1) << endl;
131     }
132     return 0;
133 }

 

轉載於:https://www.cnblogs.com/baocong/p/7385504.html

相關文章