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 按位 ...
随机推荐
- MySQL8的注意点
最近使用MySQL8,发现两个问题,略记如下: 1. 新建用户无法使用JDBC或者Navicat等登陆,报错信息为 认证失败 ,原因为 新版 MySQL 认证插件变化(变为caching_sha2_p ...
- 为什么 APM 能提升 IT 团队工作质量?
“有必要吗?”这是很多 IT 专业人员在尝试向团队内部推荐应用程序性能管理价值时所面临的问题.APM(应用程序性能管理)能为公司节约成本,提高内部工作效率,并真实了解用户对公司的系统和产品是否满意.除 ...
- 03-12_MBean层次结构
本文重点: Mbeans层次结构与WLST关系介绍 WebLogic Mbeans的类型 weblogic服务器的MBeans生命周期 Mbeans层次结构与WLST关系介绍: ...
- [HDFS_add_2] SecondaryNameNode 滚动 NameNode 数据流程
0. 说明 在 将 SecondaryNameNode 配置到 s105 节点上 的基础上进行 SecondaryNameNode 滚动 NameNode 数据流程 分析 1. SecondaryNa ...
- YUM仓库服务与PXE网络装机
1.yum:基于RPM包构建软件更新机制自动解决依赖关系,软件包由软件包库提供 提供方式:ftp服务:ftp://IP地址/仓库目录 Http服务:http :// IP地址/仓库目录 本地目录:f ...
- zk理解(转载自邬兴亮---www.cnblogs.com/wuxl360/p/5817471.html)
一.分布式协调技术 在给大家介绍ZooKeeper之前先来给大家介绍一种技术——分布式协调技术.那么什么是分布式协调技术?那么我来告诉大家,其实分布式协调技术 主要用来解决分布式环境当中多个进程之间的 ...
- 点击事件click和onclick的区别
一句话:$(selector).click()事件只能绑定静态元素.$(selector).on('click',function(){ })支持动态绑定元素. 如果是动态生成的元素,绑定事件只能用o ...
- 描述各自页面的 page
一个小程序页面由四个文件组成(注意:为了方便开发者减少配置项,描述页面的四个文件必须具有相同的路径与文件名).分别是: 页面 Page(JS文件) Page(Object) 函数用来注册一个页面.接受 ...
- __iter___和__next__方法
__iter__方法变成一个迭代器类对象, 迭代器类要实现__next__方法
- Perfect Pth Powers pku-1730(筛+合数分解)
题意:x可以表示为bp, 求这个p的最大值,比如 25=52, 64=26, 然后输入x 输出 p 就是一个质因子分解.算法.(表示数据上卡了2个小时.) 合数质因子分解模板. ]; ]; ; ;n ...