传送门

解题思路:

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

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

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

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

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

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

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

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

最后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. cocos2d-js导弹跟踪算法(一边追着目标移动一边旋转角度)

    跟踪导弹 function(targetPosition){ // 让物体朝目标移动的方法 ; var targetPoint = targetPosition; var thisPoint = cc ...

  2. ListView阻尼效果

    效果图省略.. . activity_main.xml(仅仅有一个自己定义ListView) <RelativeLayout xmlns:android="http://schemas ...

  3. Perl Learning 5 Hash

    [本文原创,未经同意请勿转载] 哈希是一种数据结构,它和数组的相似之处在于能够容纳随意多的值并能按需取用,而它和数组的不同在于索引方式,数组是以数字来索引.哈希则以名字来索引.也就是说.哈希的索引值, ...

  4. 如何下载最新版的 Adobe Flash Player

    如何下载最新版的 Adobe Flash Player 中国访客用代理访问下面的链接,否则会自动跳转到 https://www.flash.cn/ 当我们从 https://get.adobe.com ...

  5. vue2.0-elementUI

    main.js import Vue from 'vue' import App from './App.vue' import ElementUI from 'element-ui' import ...

  6. BZOJ3511: 土地划分

    [传送门:BZOJ3511] 简要题意: 给出n个点,m条边,每个点有A和B两种形态,一开始1为A,n为B 给出VA[i]和VB[i],表示第i个点选择A和B形态的价值 每条边给出x,y,EA,EB, ...

  7. Android setBackgroundResource和setBackgroundDrawable和用法

    两个方法的效果是一样,只是区别于效率! playBtn.setBackgroundResource(R.drawable.pause_selecor); 从上面可以看出来是从资源文件中获取drawab ...

  8. 实现图片懒加载(lazyload)

    对页面加载速度影响最大的就是图片,一张普通的图片可以达到几M的大小,而代码也许就只有几十KB.当页面图片很多时,页面的加载速度缓慢,几S钟内页面没有加载完成,也许会失去很多的用户. 所以,对于图片过多 ...

  9. installp 操作

    installp  软件安装和升级工具     1.查看某个已应用更可被提交或拒绝的文件集) installp -s   2. 应用更新TCP/IP软件( /usr/sys/inst.images ) ...

  10. Cisco路由器交换机配置命令详解

    1. 交换机支持的命令: 交换机基本状态:switch: :ROM状态, 路由器是rommon>hostname> :用户模式hostname# :特权模式hostname(config) ...