传送门

解题思路:

这道题给了我们一个崭新的角度来看线段树。

我们常常使用的线段树是维护区间的函数的。

这里呢,提示我们线段树其实还可以维护递推。

美好的矩阵递推性质支持了这一功能。

或者说,对于递推项求和,可以使用线段树维护矩阵。

区间向前递推可以用懒惰标记记录递推矩阵。

区间的查询可以是子节点矩阵和。

这其实也是满足分配率的。

最后pushup,pushdown搞一搞就好了。

代码(闲来无事卡常码风突变):

 #include<cstdio>
#include<cstring>
#include<algorithm>
#define lll spc<<1
#define rrr spc<<1|1
typedef unsigned long long lnt;
typedef unsigned int ixt;
const lnt mod=(lnt)(1e9+);
struct squ{
lnt s[][];
inline void res(void)
{
memset(s,,sizeof(s));
return ;
}
inline void O1(void)
{
for(register int i=;i<;i++)
s[i][i]=;
return ;
}
inline squ friend operator + (const squ &a,const squ &b)
{
squ ans;
for(register int i=;i<;i++)
{
for(register int j=;j<;j++)
{
ans.s[i][j]=(a.s[i][j]+b.s[i][j])%mod;
}
}
return ans;
}
inline squ friend operator * (const squ &a,const squ &b)
{
squ ans;
for(register int i=;i<;i++)
{
for(register int j=;j<;j++)
{
ans.s[i][j]=;
for(register int k=;k<;k++)
{
ans.s[i][j]=(ans.s[i][j]+a.s[i][k]*b.s[k][j])%mod;
}
}
}
return ans;
}
inline squ friend operator ^ (squ a,lnt b)
{
squ ans=a;
b--;
while(b)
{
if(b&)
ans=ans*a;
a=a*a;
b=b/;
}
return ans;
}
}sta,pro;
struct trnt{
squ sum;
squ lzt;
bool op;
}tr[];
ixt n,m;
ixt a[];
inline void read(ixt &ans)
{
ans=;
char ch=getchar();
while(ch<''||ch>'')
ch=getchar();
while(ch>=''&&ch<='')
ans=ans*+ch-'',ch=getchar();
return ;
}
inline squ Fib(const lnt &x)
{
squ tmp=pro^x;
return tmp*sta;
}
inline void pushup(const int &spc)
{
tr[spc].sum=tr[lll].sum+tr[rrr].sum;
return ;
}
inline void add(const int &spc,const squ &v)
{
tr[spc].op=true;
tr[spc].lzt=v*tr[spc].lzt;
tr[spc].sum=v*tr[spc].sum;
return ;
}
inline void pushdown(const int &spc)
{
if(tr[spc].op)
{
add(lll,tr[spc].lzt);
add(rrr,tr[spc].lzt);
tr[spc].lzt.res();
tr[spc].lzt.O1();
tr[spc].op=;
}
return ;
}
inline void build(const int &l,const int &r,const int &spc)
{
tr[spc].lzt.res();
tr[spc].lzt.O1();
if(l==r)
{
tr[spc].sum=Fib(a[l]);
return ;
}
int mid=(l+r)>>;
build(l,mid,lll);
build(mid+,r,rrr);
pushup(spc);
return ;
}
inline void update(const int &l,const int &r,const int &ll,const int &rr,const int &spc,const squ &v)
{
if(ll>r||l>rr)
return ;
if(ll<=l&&r<=rr)
{
add(spc,v);
return ;
}
int mid=(l+r)>>;
pushdown(spc);
update(l,mid,ll,rr,lll,v);
update(mid+,r,ll,rr,rrr,v);
pushup(spc);
return ;
}
inline squ query(const int &l,const int &r,const int &ll,const int &rr,const int &spc)
{
squ ans;
ans.res();
if(l>rr||ll>r)
return ans;
if(ll<=l&&r<=rr)
return tr[spc].sum;
int mid=(l+r)>>;
pushdown(spc);
return query(l,mid,ll,rr,lll)+query(mid+,r,ll,rr,rrr);
}
int main()
{
sta.s[][]=;
sta.s[][]=;
pro.s[][]=;
pro.s[][]=;
pro.s[][]=;
read(n);
read(m);
for(register int i=;i<=n;i++)
scanf("%d",&a[i]);
build(,n,);
while(m--)
{
ixt opt;
read(opt);
if(opt==)
{
ixt l,r,x;
read(l);
read(r);
read(x);
if(!x)
continue;
squ tmp=pro^x;
update(,n,l,r,,tmp);
}else{
ixt l,r;
read(l);
read(r);
printf("%I64u\n",(query(,n,l,r,).s[][]%mod+mod)%mod);
}
}
return ;
}

Codeforces 718C. Sasha and Array(线段树)的更多相关文章

  1. codeforces 719E E. Sasha and Array(线段树)

    题目链接: E. Sasha and Array time limit per test 5 seconds memory limit per test 256 megabytes input sta ...

  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. 【Codeforces718C】Sasha and Array 线段树 + 矩阵乘法

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

  4. CodeForces 718C Sasha and Array

    线段树. 线段树维护区间矩阵和,操作都是最简单的线段树.$lazy$标记不要记录乘了几次,直接记录乘了几次之后的矩阵就可以了,不然每次下传的时候再算一遍时间复杂度会提高. #pragma commen ...

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

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

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

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

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

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

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

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

  9. Codeforces 719 E. Sasha and Array (线段树+矩阵运算)

    题目链接:http://codeforces.com/contest/719/problem/E 题意:操作1将[l, r] + x; 操作2求f[l] + ... + f[r]; 题解:注意矩阵可以 ...

随机推荐

  1. 【C#】C#托付和事件的实例解说

    using System; namespace delegate_event { // 定义一个猫类 class Cat { // 定义一个名字字段 private string name; // 创 ...

  2. vim使用(二):经常使用功能

    1. vim经常使用功能 vim的经常使用功能.包含块的选择.复制,多文件的编辑.多窗体等功能. 2. vim块选择 块选择是将文档中的一块能够选择复制,粘贴,不用整行的处理. 按下 v , V . ...

  3. 27.AngularJS 下载地址

    转自:https://www.cnblogs.com/best/tag/Angular/ 各个 angular.js 版本下载: https://github.com/angular/angular. ...

  4. LXDE桌面初始设置,Fedora27系统。

    一.主题安装主题:方法1.通过软件源安装主题,默认xfce安装的主题有限不一定符合我们的口味. [root@Fedora ~]# dnf search themes      #搜索可用主题 通过上面 ...

  5. Ubuntu源配置

    一.图形界面配置 新手推荐使用图形界面配置: 系统工具 -> 软件和更新-> Ubuntu软件-> 下载自:-> 其他站点  点击 选择最佳服务器(将通过连接测试确定最佳镜像) ...

  6. python3之开发环境PyCharm配置

    1. 安装PyCharm(安装时注意选择python),地址: https://www.jetbrains.com/pycharm/ 2. 安装python 地址: https://www.pytho ...

  7. 【Linux系统引导过程】

    *** 第一步 开机自检 根据主板BIOS中的启动顺序,移交系统控制权. 当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它. 这是因为BIO ...

  8. Unity 实现Log实时输出到屏幕或控制台上<一>

    本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/49818953 作者:car ...

  9. 处理SpringMVC的时间错误:Field error in object 'sysDatumedetai' on field 'storagetime': rejected value [2017-11-27];

    错误: 十一月 27, 2017 8:26:11 下午 org.apache.catalina.core.StandardWrapperValve invoke 严重: Servlet.service ...

  10. Linux学习总结(7)——阿里云centeros服务器上安装 jdk,tomcat,mysql

    查看服务器的系统版本 # cat /etc/issue 查看服务器是64位还是32位 #uname -a      或者用:#getconf LONG_BIT 查看当前有没有安装jdk #rpm -q ...