题解

(不会矩阵加速的先去学矩阵加速)

反正我想不到线段树维护矩阵。我太菜了。

我们在线段树上维护一个区间的斐波那契的列矩阵的和。

然后询问时提取每个符合题意列矩阵的答案项(不是列矩阵存了两项吗,一个是当前项,一个是用来递推的)

因为矩阵乘有结合律所以区间加这个操作就直接区间乘变换矩阵的x次方就行。

然后记得开long long

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const long long mod=1e9+;
const long long N=;
long long n,m;
struct jz{
long long a[][];
}e,h,be,f[N],ma;
struct tree{
long long l,r;
jz sum,lazy;
}tr[N*];
jz jzc(jz a,jz b,jz c){
for(long long i=;i<=;i++)
for(long long j=;j<=;j++)
for(long long k=;k<=;k++){
c.a[i][j]+=a.a[i][k]*b.a[k][j];
c.a[i][j]%=mod;
}
return c;
}
jz ksm(long long b,jz x){
jz ans;
ans=ma;
while(b){
if(b&){
ans=jzc(ans,x,h);
}
b>>=;
x=jzc(x,x,h);
}
return ans;
}
void update(long long now){
tr[now].sum.a[][]=(tr[now*].sum.a[][]+tr[now*+].sum.a[][])%mod;
tr[now].sum.a[][]=(tr[now*].sum.a[][]+tr[now*+].sum.a[][])%mod;
}
void build(long long l,long long r,long long now){
tr[now].l=l;tr[now].r=r;tr[now].lazy=ma;
if(l==r){
tr[now].sum=f[l];
return;
}
long long mid=(l+r)>>;
build(l,mid,now*);
build(mid+,r,now*+);
update(now);
}
bool pd(jz a,jz b){
for(long long i=;i<=;i++)
for(long long j=;j<=;j++)
if(a.a[i][j]!=b.a[i][j])return false;
return true;
}
void pushdown(long long now){
if(pd(tr[now].lazy,ma))return;
tr[now*].sum=jzc(tr[now*].sum,tr[now].lazy,h);
tr[now*+].sum=jzc(tr[now*+].sum,tr[now].lazy,h);
tr[now*].lazy=jzc(tr[now*].lazy,tr[now].lazy,h);
tr[now*+].lazy=jzc(tr[now*+].lazy,tr[now].lazy,h);
tr[now].lazy=ma;
}
void add(long long l,long long r,long long now,jz x){
pushdown(now);
if(tr[now].l==l&&tr[now].r==r){
tr[now].sum=jzc(tr[now].sum,x,h);
tr[now].lazy=x;
return;
}
long long mid=(tr[now].l+tr[now].r)>>;
if(l>mid)add(l,r,now*+,x);
else if(r<=mid)add(l,r,now*,x);
else{
add(l,mid,now*,x);
add(mid+,r,now*+,x);
}
update(now);
}
long long query(long long l,long long r,long long now){
pushdown(now);
if(tr[now].l==l&&tr[now].r==r){
return tr[now].sum.a[][];
}
long long mid=(tr[now].l+tr[now].r)>>;
if(l>mid)return query(l,r,now*+);
else if(r<=mid)return query(l,r,now*);
else return (query(l,mid,now*)+query(mid+,r,now*+))%mod;
}
int main(){
scanf("%lld%lld",&n,&m);
e.a[][]=;e.a[][]=e.a[][]=e.a[][]=;
be.a[][]=;be.a[][]=;
for(long long i=;i<=;i++)
for(long long j=;j<=;j++)
if(i==j)ma.a[i][j]=;
else ma.a[i][j]=;
for(long long i=;i<=n;i++){
long long x;
scanf("%lld",&x);
if(x==)f[i]=be;
else f[i]=jzc(be,ksm(x-,e),h);
}
build(,n,);
for(long long i=;i<=m;i++){
long long k;
scanf("%lld",&k);
if(k==){
long long l,r,x;
scanf("%lld%lld%lld",&l,&r,&x);
add(l,r,,ksm(x,e));
}
else{
long long l,r;
scanf("%lld%lld",&l,&r);
printf("%lld\n",query(l,r,));
}
}
return ;
}

CF718C Sasha and Array(线段树维护矩阵)的更多相关文章

  1. CF719E. Sasha and Array [线段树维护矩阵]

    CF719E. Sasha and Array 题意: 对长度为 n 的数列进行 m 次操作, 操作为: a[l..r] 每一项都加一个常数 C, 其中 0 ≤ C ≤ 10^9 求 F[a[l]]+ ...

  2. Codeforces Round #373 (Div. 2) E. Sasha and Array 线段树维护矩阵

    E. Sasha and Array 题目连接: http://codeforces.com/contest/719/problem/E Description Sasha has an array ...

  3. CF718C Sasha and Array 线段树 + 矩阵乘法

    有两个操作: 将 $[l,r]$所有数 + $x$ 求 $\sum_{i=l}^{r}fib(i)$ $n=m=10^5$   直接求不好求,改成矩阵乘法的形式:  $a_{i}=M^x\times ...

  4. CF718C Sasha and Array [线段树+矩阵]

    我们考虑线性代数上面的矩阵知识 啊呸,是基础数学 斐波那契的矩阵就不讲了 定义矩阵 \(f_x\) 是第 \(x\) 项的斐波那契矩阵 因为 \(f_i * f_j = f_{i+j}\) 然后又因为 ...

  5. CF718C Sasha and Array 线段树+矩阵加速

    正解:线段树 解题报告: 传送门! 首先这种斐波拉契,又到了1e9的范围,又是求和什么的,自然而然要想到矩阵加速昂 然后这里主要是考虑修改操作,ai+=x如果放到矩阵加速中是什么意思呢QAQ? 那不就 ...

  6. 线段树维护矩阵【CF718C】 Sasha and Array

    Description 有一个长为\(n\)的数列\(a_{1},a_{2}...a_{n}\),你需要对这个数列维护如下两种操作: \(1\space l \space r\space x\) 表示 ...

  7. 【Codeforces718C】Sasha and Array 线段树 + 矩阵乘法

    C. Sasha and Array time limit per test:5 seconds memory limit per test:256 megabytes input:standard ...

  8. Subsequence Count 2017ccpc网络赛 1006 dp+线段树维护矩阵

    Problem Description Given a binary string S[1,...,N] (i.e. a sequence of 0's and 1's), and Q queries ...

  9. hdu 5068 线段树维护矩阵乘积

    http://acm.hdu.edu.cn/showproblem.php?pid=5068 题意给的略不清晰 m个询问:从i层去j层的方法数(求连段乘积)或者修改从x层y门和x+1层z门的状态反转( ...

随机推荐

  1. Opencv 编译

    转载 https://www.cnblogs.com/xinxue/p/5766756.html OpenCV 3.4 版本,圣诞节前发布了,该版本新增了一种去掉视频背景的算法,dnn 模块的进一步改 ...

  2. Idea怎么添加类的注释模板

    Idea添加类的注释模板: File-->Settings-->Live Templates-->点击+号按钮添加模板 添加自定义分组名,添加自定义模板名,如图所示add,添加完成后 ...

  3. (转载) Android studio如何生成aar包

    Android studio如何生成aar包 标签: Android studio如何生成aaAndroid studio aarAndroid 如何生成aar包 2016-12-21 14:42 1 ...

  4. hiho 172周 - 二维树状数组模板题

    题目链接 描述 You are given an N × N matrix. At the beginning every element is 0. Write a program supporti ...

  5. Activiti 23张表及7大服务详解

    7大服务介绍 服务名称 描述 RepositoryService Activiti 中每一个不同版本的业务流程的定义都需要使用一些定义文件,部署文件和支持数据 ( 例如 BPMN2.0 XML 文件, ...

  6. 如何取未知Json字符串 某个主键取对应的Value

    需添加引用using Newtonsoft.Json; string strJon  "Json 字符串"; JObject obj = JObject.Parse(strJon  ...

  7. css part 2

    CSS 盒子模型 margin:            用于控制元素与元素之间的距离:margin的最基本用途就是控制元素周围空间的间隔,从视觉角度上达到相互隔开的目的. padding:       ...

  8. continue和break

    <script type="text/javascript"> var i=1; computer: while(true){ i++; switch(i){ case ...

  9. ES 新增字符串方法

    话不多说,直接开鲁 1. startsWith() 作用: 检测字符串以什么开头 实例: let str = "www.qjzzj.top"; console.log(str.st ...

  10. npm install报错类似于npm WARN tar ENOENT: no such file or directory, open '***\node_modules\.staging\***

    报错类似于如下图 解决方法: 删除文件 package-lock.json,再重新执行npm i或者npm install