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。

 /* basic header */
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cstring>
#include <cmath>
#include <cstdint>
#include <climits>
#include <float.h>
/* STL */
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <array>
#include <iterator>
/* define */
#define ll long long
#define dou double
#define pb emplace_back
#define mp make_pair
#define fir first
#define sec second
#define sot(a,b) sort(a+1,a+1+b)
#define rep1(i,a,b) for(int i=a;i<=b;++i)
#define rep0(i,a,b) for(int i=a;i<b;++i)
#define repa(i,a) for(auto &i:a)
#define eps 1e-8
#define int_inf 0x3f3f3f3f
#define ll_inf 0x7f7f7f7f7f7f7f7f
#define lson curPos<<1
#define rson curPos<<1|1
/* namespace */
using namespace std;
/* header end */ const int maxn = 1e5 + ;
const int mod = 1e9 + ; struct Matrix
{
ll data[][];
Matrix()
{
data[][] = data[][] = data[][] = data[][] = ;
}
//变为转移矩阵
inline void tran()
{
data[][] = data[][] = data[][] = , data[][] = ;
}
//初始化为对角矩阵
inline void init()
{
*this = Matrix();
rep1(i, , ) data[i][i] = ;
}
//返回矩阵第x行
inline ll *operator[](int x)
{
return data[x];
}
//定义矩阵乘法
inline void operator*=(Matrix &rhs)
{
Matrix qAns;
rep1(k, , )
{
rep1(i, , )
{
rep1(j, , )
qAns[j][i] = (qAns[j][i] + data[j][k] * rhs[k][i]) % mod;
}
}
*this = qAns;
}
//矩阵快速幂
inline void operator^=(int x)
{
Matrix base = *this, qAns;
rep1(i, , ) qAns[i][i] = ;
for (register int i = x; i; i >>= , base *= base)
if (i & ) qAns *= base;
*this = qAns;
}
inline void operator+=(Matrix &rhs)
{
rep1(i, , )
{
rep1(j, , )
{
data[i][j] = (data[i][j] + rhs[i][j]) % mod;
}
}
}
//输出
inline void pr()
{
rep1(t, , )
{
rep1(i, , ) printf("%d ", data[t][i]);
puts("");
}
}
} seg[maxn << ], add[maxn << ]; int n, m;
Matrix qAns, markdown;
bool lazyTag[maxn << ]; inline void pushdown(int curPos)
{
if (!lazyTag[curPos]) return;
seg[lson] *= add[curPos]; seg[rson] *= add[curPos];
add[lson] *= add[curPos]; add[rson] *= add[curPos];
lazyTag[lson] = lazyTag[rson] = ;
add[curPos].init(); lazyTag[curPos] = ;
} void build(int curPos, int curL, int curR)
{
if (curL == curR)
{
seg[curPos].tran();
add[curPos].init();
int tmp; scanf("%d", &tmp);
seg[curPos] ^= tmp - ;
return;
}
int mid = (curL + curR) >> ;
add[curPos].init();
build(lson, curL, mid); build(rson, mid + , curR);
seg[curPos] = Matrix();
seg[curPos] += seg[lson]; seg[curPos] += seg[rson];
} void update(int curPos, int curL, int curR, int qL, int qR)
{
if (qL <= curL && curR <= qR)
{
add[curPos] *= markdown; seg[curPos] *= markdown; lazyTag[curPos] = ;
return;
}
int mid = (curL + curR) >> ;
pushdown(curPos);
if (qL <= mid) update(lson, curL, mid, qL, qR);
if (mid < qR) update(rson, mid + , curR, qL, qR);
seg[curPos] = Matrix();
seg[curPos] += seg[lson]; seg[curPos] += seg[rson];
} void query(int curPos, int curL, int curR, int qL, int qR)
{
if (qL <= curL && curR <= qR)
{
qAns += seg[curPos];
return;
}
int mid = (curL + curR) >> ;
pushdown(curPos);
if (qL <= mid) query(lson, curL, mid, qL, qR);
if (mid < qR) query(rson, mid + , curR, qL, qR);
seg[curPos] = Matrix();
seg[curPos] += seg[lson]; seg[curPos] += seg[rson];
} int main()
{
scanf("%d%d", &n, &m);
build(, , n);
rep1(cnt, , m)
{
int op; scanf("%d", &op);
if (op == )
{
int x, y, t; scanf("%d%d%d", &x, &y, &t);
markdown.tran(); markdown ^= t;
update(, , n, x, y);
}
else
{
int x, y; scanf("%d%d", &x, &y);
qAns = Matrix();
query(, , n, x, y);
printf("%lld\n", (qAns[][] + qAns[][]) % mod);
}
}
return ;
}

Codeforces 718C solution的更多相关文章

  1. CodeForces 718C Sasha and Array

    线段树. 线段树维护区间矩阵和,操作都是最简单的线段树.$lazy$标记不要记录乘了几次,直接记录乘了几次之后的矩阵就可以了,不然每次下传的时候再算一遍时间复杂度会提高. #pragma commen ...

  2. CodeForces 718C && HDU 3572 && Constellation

    Point 1. 区间乘以一个数/矩阵的幂时,不要用指数相加的方法. 而要用直接维护mulv[x]表示区间要乘多少. 不然的话,空加一个logn 2. 要点在于,冲突的点连边,形成二分图,对于在同一个 ...

  3. Codeforces 718C 线段树+矩乘

    题意: 维护一个序列,支持两种操作:1.区间[l,r]的权值+x2.询问区间[l,r]的函数和,即∑fib(x)这里的函数即斐波那契函数数据范围:1≤n,q≤105 思路:一般求斐波那契函数的方法可以 ...

  4. Codeforces 718C. Sasha and Array(线段树)

    传送门 解题思路: 这道题给了我们一个崭新的角度来看线段树. 我们常常使用的线段树是维护区间的函数的. 这里呢,提示我们线段树其实还可以维护递推. 美好的矩阵递推性质支持了这一功能. 或者说,对于递推 ...

  5. BUPT2017 wintertraining(15) #1 题解

    拖了一周才完成的题解,抛出一个可爱的表情 (っ'-')╮ =͟͟͞͞❤️.对我来说E.F比较难,都是线段树的题,有点久没写了. A - Infinite Sequence CodeForces - 6 ...

  6. Codeforces Round #383 (Div. 2) B. Arpa’s obvious problem and Mehrdad’s terrible solution —— 异或

    题目链接:http://codeforces.com/contest/742/problem/B B. Arpa's obvious problem and Mehrdad's terrible so ...

  7. 【codeforces 742B】Arpa’s obvious problem and Mehrdad’s terrible solution

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  8. Codeforces Round #383 (Div. 2) B. Arpa’s obvious problem and Mehrdad’s terrible solution

    B. Arpa’s obvious problem and Mehrdad’s terrible solution time limit per test 1 second memory limit ...

  9. 老年OIer的Python实践记—— Codeforces Round #555 (Div. 3) solution

    对没错下面的代码全部是python 3(除了E的那个multiset) 题目链接:https://codeforces.com/contest/1157 A. Reachable Numbers 按位 ...

随机推荐

  1. 安卓开发_浅谈ListView(自定义适配器)

    ListView作为一个实际开发中使用率非常高的视图,一般的系统自带的适配器都无法满足开发中的需求,这时候就需要开发人员来自定义适配器使得ListView能够有一个不错的显示效果 有这样一个Demo ...

  2. BD是什么角色

    BD是什么角色? 在一般创业公司里面,有了产品接下来就是运营了,而运营中很重要的一点就是BD,也就是所谓商务拓展了,俗一点说就是生意的合作拓展 https://www.jianshu.com/p/7d ...

  3. [201804012]关于hugepages 3.txt

    [201804012]关于hugepages 3.txt --//有一段时间我一直强调安装oracle一定要配置hugepage,因为现在的服务器内存越来越大,如果还使用4K的页面表,如果内存表占用内 ...

  4. Oracle EBS FA 资产取值

    SELECT fb.book_type_code, fth.ASSET_NUMBER, fdh.units_assigned, fdh.assigned_to, pf.FULL_NAME, fl.se ...

  5. Mac显示器不亮

    上班的时候mac连接上显示器,但是显示器并没有亮,于是乎各种插拔ing...偶尔一两次还可以接受,但是天天这样小身板招架不住呀,于是乎终于找到一个可以让显示器快速亮起的方法,遂赶紧分享给各位小火鸡~ ...

  6. 软件工程实践_Task2_sudoku

    软工实践_Task2 标签(空格分隔): 软工实践 相关要求:第二次作业--个人项目实战 github:传送门 解题思路 先是一点杂谈. 首先,看完作业要求之后,心里先有个大概的框架. 语言:C++ ...

  7. C++添加热键和捕获组合键

    一.热键注册 步骤一:声明一个全局量int hotkeyId=1: 步骤二:窗体创建的时候注册: int result= RegisterHotKey(this->GetHWND(), hotk ...

  8. Tronado自定义Form组件

    Tronado自定义Form组件 一.获取类里面的静态属性以及动态属性的方法 方式一: # ===========方式一================ class Foo(object): user ...

  9. 2018-2019-2 网络对抗技术 20165318 Exp3 免杀原理与实践

    2018-2019-2 网络对抗技术 20165318 Exp3 免杀原理与实践 免杀原理及基础问题回答 实验内容 任务一:正确使用msf编码器,msfvenom生成如jar之类的其他文件,veil- ...

  10. Kafka远程调试简单记录

    Kafka启动脚本: ./kafka-server-start.sh -daemon ../config/server.properties 最终翻阅脚本可以确定是调用kafka-run-class. ...