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. Source Insight里头文件注释和函数头的注释

    1.将下述代码拷贝入一个文件,扩展名为em 2.打开BASE工程,添加本文件,并重新同步 3.添加hh_InsertFuncHeader的快捷键,即为函数头注释,光标需要放在函数名那一行,否则无效 4 ...

  2. MailKit帮助类

    public class EmailHelp { /// <summary> /// Smtp服务器地址 /// </summary> private static reado ...

  3. 面向对象的封装与隐藏 this

    当我们创建一个对象的时候,我们可以通过‘对象.属性’的方式,对对象的属性进行赋值. 这里赋值操作要受到属性的数据类型和存储范围的制约,但是除此之外,没有其他制约条件. 但是实际问题中我们需要给这个属性 ...

  4. [MapReduce_add_2] MapReduce 实现年度最高气温统计

    0. 说明 编写 MapReduce 程序实现年度最高气温统计 1. 气温数据分析 气温数据样例如下: ++023450FM-+000599999V0202701N015919999999N00000 ...

  5. 系统运维|IIS的日志设置

    摘要: 1.服务器告警,磁盘资源不足 2.检查发现是IIS日志没有清理并且设置有误.在E盘占用了200G的空间 3.原则上IIS日志不能放在C盘,避免C盘写满了导致操作系统异常 4.附上IIS日志按天 ...

  6. jenkins安装及配置-centos6.9

    Jenkins安装及配置 目录 1.安装java. 2 1.1安装说明... 2 1.2创建java目录... 2 1.3下载并解压... 2 1.4设置环境变量... 2 1.5验证JDK有效性.. ...

  7. 第6章 linux的文件权限与目录配置

    6.1用户与用户组 用户,自己的抽屉 用户组,自己的家 其他人(others),外人 root,天神 /etc/passwd 所有的系统上的账号与一般身份用户,root的相关信息 /etc/shado ...

  8. 如何轻松搞定 笔记本搜不到WIFI信号问题

    经常用电脑的同志肯定遇到过:一开机,发现右下角网络图标有个×号,wifi信号也搜不到:或者其他wifi信号能搜到,唯独自家的搜不到,是不是感觉很绝望啊,居然被wifi欺负到身上了,这也太憋屈了吧. 此 ...

  9. win10锁屏或睡眠一段时间后弹不出登录框

    win10锁屏或睡眠一段时间后弹不出登录框 文:铁乐与猫 通常发生在win10更新到10周年版后发生,也就是会卡在登录状态,但不见输入登录框. 我出现这种情况的时候不是很严重,一般等久些也能出现,但问 ...

  10. python框架面试题联系

    1.对 MVC,MVT 解读的理解? M:Model,模型,和数据库进行交互 V:View,视图,负责产生 Html 页面 C:Controller,控制器,接收请求,进行处理,与 M 和 V 进行交 ...