Description

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

  1. \(1\space l \space r\space x\) 表示将数列中的\(a_{l},a_{l+1}...a_{r-1},a_{r}\)加上\(x\)
  2. \(2\space l\space r\) 表示要你求出\(\sum_{i=l}^{r}fib(a_{i})\)对\(10^9+7\)取模后的结果

fib(x)fib(x)表示的是斐波那契的第\(x\)项,\(fib(1)=1,fib(2)=1,fib(i)=fib(i-1)+fib(i-2)(i>2)\)

线段树维护矩阵。

emmm,吓人。

看着题解码

有些懵逼这种矩乘写法。

为啥最普通的矩阵乘法不行???

调了半天发现快速幂里面的\(for\)后面加了个分号??

区间修改操作即为原矩阵乘上转移矩阵的\(x\)次方。

话说和我推的式子貌似又不是很一样???QwQ?

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#define int long long
#define R register using namespace std; const int mod=1e9+7;
const int gz=100001; inline void in(R int &x)
{
int f=1;x=0;char s=getchar();
while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
while(isdigit(s)){x=x*10+s-'0';s=getchar();}
x*=f;
} int n,m,val[gz]; struct Matrix
{
int m[4][4];
inline void clear()
{
for(R int i=0;i<4;i++)
for(R int j=0;j<4;j++)
m[i][j]=0;
}
inline void pre()
{
for(R int i=0;i<4;i++)m[i][i]=1;
} inline bool emp()
{
return (m[1][1]==1 and m[1][2]==0 and m[2][1]==0 and m[2][2]==1);
} Matrix operator *(const Matrix &a)const
{
Matrix tmp;tmp.clear();
for(R int i=1;i<=2;i++)
for(R int k=1;k<=2;k++)
for(R int j=1;j<=2;j++)
tmp.m[i][j]=(tmp.m[i][j]+m[i][k]*a.m[k][j])%mod;
return tmp;
} friend Matrix operator +(Matrix a,Matrix b)
{
Matrix tmp;tmp.clear();
for(R int i=1;i<=2;i++)
for(R int j=1;j<=2;j++)
tmp.m[i][j]=(a.m[i][j]+b.m[i][j])%mod;
return tmp;
}
}; Matrix fir,fb;
Matrix tr[gz<<2],tg[gz<<2]; #define ls o<<1
#define rs o<<1|1 inline void up(R int o)
{
tr[o]=tr[ls]+tr[rs];
} inline Matrix ksm(R Matrix a,R int y)
{
Matrix res;res.clear();res.pre();
for(;y;y>>=1,a=a*a)
if(y&1)res=res*a;
return res;
} void build(R int o,R int l,R int r)
{
tr[o].clear();tg[o].clear();tg[o].pre();
if(l==r)
{
tr[o]=fir*ksm(fb,val[l]-1);
return ;
}
R int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
up(o);
} inline void down(R int o)
{
if(tg[o].emp())return;
tr[ls]=tr[ls]*tg[o];
tr[rs]=tr[rs]*tg[o];
tg[ls]=tg[ls]*tg[o];
tg[rs]=tg[rs]*tg[o];
tg[o].clear();
tg[o].pre();
} void change(R int o,R int l,R int r,R int x,R int y,R Matrix k)
{
if(x<=l and y>=r)
{
tr[o]=tr[o]*k;
tg[o]=tg[o]*k;
return;
}
down(o);
R int mid=(l+r)>>1;
if(x<=mid) change(ls,l,mid,x,y,k);
if(y>mid)change(rs,mid+1,r,x,y,k);
up(o);
} inline Matrix query(R int o,R int l,R int r ,R int x,R int y)
{
if(x<=l and y>=r)return tr[o];
down(o);
Matrix res;res.clear();
R int mid=(l+r)>>1;
if(x<=mid) res=res+query(ls,l,mid,x,y);
if(y>mid) res=res+query(rs,mid+1,r,x,y);
return res;
} signed main()
{
fb.clear(),fir.clear();
fir.m[1][1]=fir.m[1][2]=1;fir.m[2][1]=fir.m[2][2]=0;
fb.m[1][1]=fb.m[1][2]=fb.m[2][1]=1;fb.m[2][2]=0;//转移矩阵
in(n),in(m);
for(R int i=1;i<=n;i++)in(val[i]);
build(1,1,n);
for(R int opt,l,r,x;m;m--)
{
in(opt);
switch(opt)
{
case 1:in(l),in(r),in(x);change(1,1,n,l,r,ksm(fb,x));break;
case 2:in(l),in(r),printf("%lld\n",query(1,1,n,l,r).m[1][2]%mod);break;
}
}
}

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

  1. CF718C Sasha and Array(线段树维护矩阵)

    题解 (不会矩阵加速的先去学矩阵加速) 反正我想不到线段树维护矩阵.我太菜了. 我们在线段树上维护一个区间的斐波那契的列矩阵的和. 然后询问时提取每个符合题意列矩阵的答案项(不是列矩阵存了两项吗,一个 ...

  2. 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 ...

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

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

  4. Codeforces 1368H - Breadboard Capacity(最小割+线段树维护矩阵乘法)

    Easy version:Codeforces 题面传送门 & 洛谷题面传送门 Hard version:Codeforces 题面传送门 & 洛谷题面传送门 首先看到这种从某一种颜色 ...

  5. Codeforces 750E - New Year and Old Subsequence(线段树维护矩阵乘法,板子题)

    Codeforces 题目传送门 & 洛谷题目传送门 u1s1 我做这道 *2600 的动力是 wjz 出了道这个套路的题,而我连起码的思路都没有,wtcl/kk 首先考虑怎样对某个固定的串计 ...

  6. Codeforces 719E (线段树教做人系列) 线段树维护矩阵

    题面简洁明了,一看就懂 做了这个题之后,才知道怎么用线段树维护递推式.递推式的递推过程可以看作两个矩阵相乘,假设矩阵A是初始值矩阵,矩阵B是变换矩阵,求第n项相当于把矩阵B乘了n - 1次. 那么我们 ...

  7. HDU 6155 Subsequence Count 线段树维护矩阵

    Subsequence Count Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 256000/256000 K (Java/Oth ...

  8. DP+线段树维护矩阵(2019牛客暑期多校训练营(第二场))--MAZE

    题意:https://ac.nowcoder.com/acm/contest/882/E 给你01矩阵,有两种操作:1是把一个位置0变1.1变0,2是问你从第一行i开始,到最后一行j有几种走法.你只能 ...

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

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

随机推荐

  1. 【题解】HNOI2017大佬

    哎……做了几个小时最后还是没能想到怼大佬的合法性到底怎么搞.写暴力爆搜感觉复杂度爆炸就没敢写 bfs / dfs 一类,后来发现在种种的约束条件下(远小于所给的 \(n, m\))复杂度完全是可以承受 ...

  2. 【题解】IOI2005River 河流

    一节语文课想出来的玩意儿,调了几个小时……可见细心&好的代码习惯是有多么的重要 (:へ:) 不过,大概竞赛最令人开心的就是能够一点一点的感受到自己的进步吧,一天比一天能够自己想出更多的题,A题 ...

  3. 安徽师大附中%你赛day4T1 金字塔 解题报告

    金字塔 题目背景: \(Zdrcl\)带着妹子们来到了胡夫金字塔周边旅游, 发现这里正在进行一个有关金字塔的游戏 题目描述: 游戏规则如下: 1. 这里的金字塔是一个 \(N\) 阶的二维金字塔. 2 ...

  4. [cdoj 1344]树状数组区间加等差数列

    题目链接:http://acm.uestc.edu.cn/#/problem/show/1344 区间加等差数列本质上就是区间修改区间查询,本来想用线段树做,结果这个题就是卡空间和时间……不得已学了区 ...

  5. tengine的安装

    tengine的安装参考此博文: http://www.cnblogs.com/zlslch/p/6035145.html (1)下载tengine的压缩包 (2)解压缩 (3)进入目录./confi ...

  6. SQLNET跟踪tnsping过程

    原文地址:SQLNET跟踪tnsping过程 作者:yingyifeng306 sqlnet是oracle提供的与网络层面交互的一个工具,比如如何解析客户端发起的连接,如何对客户端发起的连接进行辨别, ...

  7. Ant Design 使用小结

    最近公司做了一个系统,因为页面涉及的表单交互非常多,如果使用之前的 Node + Express 的开发模式效率是非常低的,因此经过考虑,最后决定使用 Node + React 的开发模式,并且使用了 ...

  8. ()()()()x()=()()()()填1-9数字

    /** Function: ()()()()x()=()()()() Developer: Date: */ #include "iostream" #include " ...

  9. 图论:2-SAT

    先象征性地描述一下问题:一组(或者一个)东西有且仅有两种选择,要么选这个,要么选那个,还有一堆的约束条件 图论问题,当然是建边跑图喽 给出模型: 模型一:两者(A,B)不能同时取 那么选择了A就只能选 ...

  10. 【SPOJ - QTREE2】树链剖分

    http://acm.hust.edu.cn/vjudge/problem/19960 题意: 有一棵N个节点的树(1<=N<=10000),N-1条边,边的编号为1~N-1,每条边有一个 ...