Codeforces 718C solution

Posted jhseng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 718C solution相关的知识,希望对你有一定的参考价值。

                         C. Sasha and Array
 
                       time limit per test : 
5 seconds
                     memory limit per test : 
256 megabytes

Description

Sasha has an array of integers a1, a2, ..., an. You have to perform m queries. There might be queries of two types:

  1. 1 l r x — increase all integers on the segment from l to r by values x;
  2. 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.

In this problem we define Fibonacci numbers as follows: f(1) = 1, f(2) = 1, f(x) = f(x - 1) + f(x - 2) for all x > 2.

Sasha is a very talented boy and he managed to perform all queries in five seconds. Will you be able to write the program that performs as well as Sasha?

Input

The first line of the input contains two integers n and m (1 ≤ n ≤ 100 000, 1 ≤ m ≤ 100 000) — the number of elements in the array and the number of queries respectively.

The next line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109).

Then follow m lines with queries descriptions. Each of them contains integers tpi, li, ri and may be xi (1 ≤ tpi ≤ 2, 1 ≤ li ≤ ri ≤ n, 1 ≤ xi ≤ 109). Here tpi = 1 corresponds to the queries of the first type and tpi corresponds to the queries of the second type.

It‘s guaranteed that the input will contains at least one query of the second type.

Output

For each query of the second type print the answer modulo 109 + 7.

Example Input
5 4
1 1 2 1 1
2 1 5
1 2 4 2
2 2 4
2 1 5
Example Output
5
7
9
Note

Initially, array a is equal to 1, 1, 2, 1, 1.

The answer for the first query of the second type is f(1) + f(1) + f(2) + f(1) + f(1) = 1 + 1 + 1 + 1 + 1 = 5.

After the query 1 2 4 2 array a is equal to 1, 3, 4, 3, 1.

The answer for the second query of the second type is f(3) + f(4) + f(3) = 2 + 3 + 2 = 7.

The answer for the third query of the second type is f(1) + f(3) + f(4) + f(3) + f(1) = 1 + 2 + 3 + 2 + 1 = 9.


没什么可说的,就是线段树维护fib递推矩阵,线段树不难写,难写的是矩阵部分,细节很多。要是封装性太强容易把代码写得很java。

  1 /* basic header */
  2 #include <iostream>
  3 #include <cstdio>
  4 #include <cstdlib>
  5 #include <string>
  6 #include <cstring>
  7 #include <cmath>
  8 #include <cstdint>
  9 #include <climits>
 10 #include <float.h>
 11 /* STL */
 12 #include <vector>
 13 #include <set>
 14 #include <map>
 15 #include <queue>
 16 #include <stack>
 17 #include <algorithm>
 18 #include <array>
 19 #include <iterator>
 20 /* define */
 21 #define ll long long
 22 #define dou double
 23 #define pb emplace_back
 24 #define mp make_pair
 25 #define fir first
 26 #define sec second
 27 #define sot(a,b) sort(a+1,a+1+b)
 28 #define rep1(i,a,b) for(int i=a;i<=b;++i)
 29 #define rep0(i,a,b) for(int i=a;i<b;++i)
 30 #define repa(i,a) for(auto &i:a)
 31 #define eps 1e-8
 32 #define int_inf 0x3f3f3f3f
 33 #define ll_inf 0x7f7f7f7f7f7f7f7f
 34 #define lson curPos<<1
 35 #define rson curPos<<1|1
 36 /* namespace */
 37 using namespace std;
 38 /* header end */
 39 
 40 const int maxn = 1e5 + 10;
 41 const int mod = 1e9 + 7;
 42 
 43 struct Matrix
 44 {
 45     ll data[2][2];
 46     Matrix()
 47     {
 48         data[0][0] = data[0][1] = data[1][0] = data[1][1] = 0;
 49     }
 50     //变为转移矩阵
 51     inline void tran()
 52     {
 53         data[0][1] = data[1][0] = data[1][1] = 1, data[0][0] = 0;
 54     }
 55     //初始化为对角矩阵
 56     inline void init()
 57     {
 58         *this = Matrix();
 59         rep1(i, 0, 1) data[i][i] = 1;
 60     }
 61     //返回矩阵第x行
 62     inline ll *operator[](int x)
 63     {
 64         return data[x];
 65     }
 66     //定义矩阵乘法
 67     inline void operator*=(Matrix &rhs)
 68     {
 69         Matrix qAns;
 70         rep1(k, 0, 1)
 71         {
 72             rep1(i, 0, 1)
 73             {
 74                 rep1(j, 0, 1)
 75                 qAns[j][i] = (qAns[j][i] + data[j][k] * rhs[k][i]) % mod;
 76             }
 77         }
 78         *this = qAns;
 79     }
 80     //矩阵快速幂
 81     inline void operator^=(int x)
 82     {
 83         Matrix base = *this, qAns;
 84         rep1(i, 0, 1) qAns[i][i] = 1;
 85         for (register int i = x; i; i >>= 1, base *= base)
 86             if (i & 1) qAns *= base;
 87         *this = qAns;
 88     }
 89     inline void operator+=(Matrix &rhs)
 90     {
 91         rep1(i, 0, 1)
 92         {
 93             rep1(j, 0, 1)
 94             {
 95                 data[i][j] = (data[i][j] + rhs[i][j]) % mod;
 96             }
 97         }
 98     }
 99     //输出
100     inline void pr()
101     {
102         rep1(t, 0, 1)
103         {
104             rep1(i, 0, 1) printf("%d ", data[t][i]);
105             puts("");
106         }
107     }
108 } seg[maxn << 2], add[maxn << 2];
109 
110 int n, m;
111 Matrix qAns, markdown;
112 bool lazyTag[maxn << 2];
113 
114 inline void pushdown(int curPos)
115 {
116     if (!lazyTag[curPos]) return;
117     seg[lson] *= add[curPos]; seg[rson] *= add[curPos];
118     add[lson] *= add[curPos]; add[rson] *= add[curPos];
119     lazyTag[lson] = lazyTag[rson] = 1;
120     add[curPos].init(); lazyTag[curPos] = 0;
121 }
122 
123 void build(int curPos, int curL, int curR)
124 {
125     if (curL == curR)
126     {
127         seg[curPos].tran();
128         add[curPos].init();
129         int tmp; scanf("%d", &tmp);
130         seg[curPos] ^= tmp - 1;
131         return;
132     }
133     int mid = (curL + curR) >> 1;
134     add[curPos].init();
135     build(lson, curL, mid); build(rson, mid + 1, curR);
136     seg[curPos] = Matrix();
137     seg[curPos] += seg[lson]; seg[curPos] += seg[rson];
138 }
139 
140 void update(int curPos, int curL, int curR, int qL, int qR)
141 {
142     if (qL <= curL && curR <= qR)
143     {
144         add[curPos] *= markdown; seg[curPos] *= markdown; lazyTag[curPos] = 1;
145         return;
146     }
147     int mid = (curL + curR) >> 1;
148     pushdown(curPos);
149     if (qL <= mid) update(lson, curL, mid, qL, qR);
150     if (mid < qR) update(rson, mid + 1, curR, qL, qR);
151     seg[curPos] = Matrix();
152     seg[curPos] += seg[lson]; seg[curPos] += seg[rson];
153 }
154 
155 void query(int curPos, int curL, int curR, int qL, int qR)
156 {
157     if (qL <= curL && curR <= qR)
158     {
159         qAns += seg[curPos];
160         return;
161     }
162     int mid = (curL + curR) >> 1;
163     pushdown(curPos);
164     if (qL <= mid) query(lson, curL, mid, qL, qR);
165     if (mid < qR) query(rson, mid + 1, curR, qL, qR);
166     seg[curPos] = Matrix();
167     seg[curPos] += seg[lson]; seg[curPos] += seg[rson];
168 }
169 
170 int main()
171 {
172     scanf("%d%d", &n, &m);
173     build(1, 1, n);
174     rep1(cnt, 1, m)
175     {
176         int op; scanf("%d", &op);
177         if (op == 1)
178         {
179             int x, y, t; scanf("%d%d%d", &x, &y, &t);
180             markdown.tran(); markdown ^= t;
181             update(1, 1, n, x, y);
182         }
183         else
184         {
185             int x, y; scanf("%d%d", &x, &y);
186             qAns = Matrix();
187             query(1, 1, n, x, y);
188             printf("%lld\n", (qAns[0][0] + qAns[0][1]) % mod);
189         }
190     }
191     return 0;
192 }

 

以上是关于Codeforces 718C solution的主要内容,如果未能解决你的问题,请参考以下文章

codeforces CF718C Sasha and Array 线段树维护矩阵

CodeForces 718C && HDU 3572

题解 CF718C Sasha and Array

718C Sasha and Array

Codeforces Round 615 div3 Solution

Educational Codeforces Round 59 Solution