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 按位 ...
随机推荐
- Flume Source 实例
Flume Source 实例 Avro Source 监听avro端口,接收外部avro客户端数据流.跟前面的agent的Avro Sink可以组成多层拓扑结构. 1 2 3 4 5 6 7 8 9 ...
- Java ——基础语法
package myhello; // 本类所在的包的路径 import af.util.AfMath; // 导入对应的类 import java.util.Random; // 导入随机数的类 p ...
- [Mac] How do I move a window whose title bar is off-screen?
有时窗口一不小心拖出视野外了,此时无法移动窗口.如何还原? 有人遇到相似问题,已有解决方法: 方法就是,菜单 Windows - Zoom 这时窗口会还原.
- validator js验证器
转自:https://github.com/jaywcjlove/validator.js 轻量级的JavaScript表单验证,字符串验证.没有依赖,支持UMD 导入js库 <script t ...
- .NET MVC 后台接受base64的上传图片
#region 配合前端的多张图片上传 #region 上传图片方法 /// <summary> /// 接口方法 /// </summary> /// <param n ...
- 【PAT】B1071 小赌怡情(15 分)
水题一道,直接贴代码 #include<cstdio> #include<string.h> int main(){ //玩家的筹码数.以及 int T,K;scanf(&qu ...
- pycharm的安装和使用小技巧
一,pycharm 1,在官网下载pycharm,版本选5.0,一定要下载专业版. 2,注册方法:注册时选择 license server,填入:http://idea.qinxi1992.cn,然后 ...
- 【HTTP缓存】浏览器缓存理论知识
时间:2016-12-12 17:51:30 作者: zhongxia 零.前言 这里主要写的是理论,具体实践的比较少,后期写一个实践教程,内容基本都是从参考文章里面抄过来的[看完文章,顺便写做下笔记 ...
- [题目] luogu P2061 [USACO07OPEN]城市的地平线City Horizon
算法 线段树 + 离散化 思路 对\((x,y,h)\)的左右端点\(x,y\)进行离散化,离散化前的原值记为\(val[i]\),对每个矩形按高度\(h\)从小到大排序. 设离散化后的端点有\(M\ ...
- Python--Windows下安装虚拟环境
为什么需要虚拟环境 在python开发中,我们可能会遇到一种情况:就是当前的项目依赖的是某一个版本,但是另一个项目依赖的是另一个版本,这样就会造成依赖冲突.在这种情况之下,我们就需要一个工具能够将这两 ...