Codeforces 718C solution
5 seconds
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 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.
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?
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.
For each query of the second type print the answer modulo 109 + 7.
5 4
1 1 2 1 1
2 1 5
1 2 4 2
2 2 4
2 1 5
5
7
9
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的更多相关文章
- CodeForces 718C Sasha and Array
线段树. 线段树维护区间矩阵和,操作都是最简单的线段树.$lazy$标记不要记录乘了几次,直接记录乘了几次之后的矩阵就可以了,不然每次下传的时候再算一遍时间复杂度会提高. #pragma commen ...
- CodeForces 718C && HDU 3572 && Constellation
Point 1. 区间乘以一个数/矩阵的幂时,不要用指数相加的方法. 而要用直接维护mulv[x]表示区间要乘多少. 不然的话,空加一个logn 2. 要点在于,冲突的点连边,形成二分图,对于在同一个 ...
- Codeforces 718C 线段树+矩乘
题意: 维护一个序列,支持两种操作:1.区间[l,r]的权值+x2.询问区间[l,r]的函数和,即∑fib(x)这里的函数即斐波那契函数数据范围:1≤n,q≤105 思路:一般求斐波那契函数的方法可以 ...
- Codeforces 718C. Sasha and Array(线段树)
传送门 解题思路: 这道题给了我们一个崭新的角度来看线段树. 我们常常使用的线段树是维护区间的函数的. 这里呢,提示我们线段树其实还可以维护递推. 美好的矩阵递推性质支持了这一功能. 或者说,对于递推 ...
- BUPT2017 wintertraining(15) #1 题解
拖了一周才完成的题解,抛出一个可爱的表情 (っ'-')╮ =͟͟͞͞❤️.对我来说E.F比较难,都是线段树的题,有点久没写了. A - Infinite Sequence CodeForces - 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 ...
- 【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 ...
- 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 ...
- 老年OIer的Python实践记—— Codeforces Round #555 (Div. 3) solution
对没错下面的代码全部是python 3(除了E的那个multiset) 题目链接:https://codeforces.com/contest/1157 A. Reachable Numbers 按位 ...
随机推荐
- (后端)如何将数据库的表导出生成Excel?
1.如何通过元数据拿到数据库的信息? 2.如何用Java生成Excel表? 3.将数据库中的表导出生成Excel案例 如何通过元数据拿到数据库的信息 元数据:描述数据的数据 Java中使用元数据的两个 ...
- 泛化之美--C++11可变模版参数的妙用
1概述 C++11的新特性--可变模版参数(variadic templates)是C++11新增的最强大的特性之一,它对参数进行了高度泛化,它能表示0到任意个数.任意类型的参数.相比C++98/03 ...
- Python之SGDRegressor
实现: # -*- coding: UTF-8 -*- import numpy as npfrom sklearn.linear_model import SGDRegressor __author ...
- 安装office2010提示要安装MSXML6.10.1129.0解决方法
系统win7 32位 安装office2010出现了错误,提示要安装MSXML6.10.1129.0解决方法 1.下载MSXML6.10.1129.0进行安装 2.若本机已安装过不管用: a.在运行里 ...
- LDAP Filter用法
#根据Pager过滤域用户 $pagers = gc D:\Operations\tmp\u.txt foreach ($p in $pagers) { $user = Get-ADUser -Fil ...
- 4.6Python多版本存在问题
返回总目录 目录: 1.展示效果: 2.操作流程: (一)展示效果: 1.多个版本python运行的情况: 2.多个版本pip运行的情况: (二)操作流程: 1.很关键的一条语句: pythonx.x ...
- web笔试
类型判断用到哪些方法? typeof和instanceof 值类型和引用类型的区别? 根据 JavaScript中的变量类型传递方式,又分为值类型和引用类型,在参数传递方式上,值类型是按值传递,引用类 ...
- [转]QGis2.9在windows下的编译以及二次开发包下载
今天心血来潮,将QGis在github上的代码更新后,又编译了一下.留意到源代码包里面的INSTALL文件有更新,于是本次编译完全基于官方的编译说明.编译过程非常顺利,除了在CMake的第一次conf ...
- 讲解Linux数据库安装
学习了linux这门课之后,就开始实践过程了,这样比较记得牢固,学以致用. 有了基本的命令,就可以试着安装数据库了. 企业环境 需要安装VMWare ESXi虚拟机,然后再在里面新建虚拟机. 镜像vm ...
- centos 7 安装python3.5.1
系统: [root@localhost ~]# cat /etc/centos-release CentOS Linux release 7.2.1511 (Core) 内核: [root@local ...