题意:给你一个数列a,a[i]表示斐波那契数列的下标为a[i],求区间对应斐波那契数列数字的和,还要求能够维护对区间内所有下标加d的操作

分析:线段树

   线段树的每个节点表示(f[i],f[i-1])这个数组

   因为矩阵的可加性,所以可以进行lazy操作

   我最开始的想法是每个节点lazy表示该区间下标加了多少,add表示该区间已经加的下标对应的矩阵乘积,这样更新lazy是O(1)的,算add是O(logn)的

   但是这样每次pushdown的时候,add下传总要多个log,会TLE

   更好的办法是lazy表示加的下标对应的矩阵乘积,这样虽然每次更新lazy是O(logn)的,但是pushdown的时候就是直接把(f[i],f[i-1])和lazy[2][2]乘起来了,是O(1)的

代码:

 #include<bits/stdc++.h>
const int maxn=1e5;
const long long mod=1e9+;
int ch[maxn*+][];
long long sum[maxn*+][],add[maxn*+][][],a[maxn+];
int len=,n,m;
void mer(long long a[][],long long b[][])
{
long long s[][];
memset(s,,sizeof(s));
for(int i=;i<;++i)
for(int j=;j<;++j)
for(int k=;k<;++k)
s[i][j]=(s[i][j]+a[i][k]*b[k][j]%mod)%mod;
for(int i=;i<;++i)
for(int j=;j<;++j)
a[i][j]=s[i][j];
}
void fib(long long num[][],long long x)
{
long long a[][]={{,},{,}};
num[][]=,num[][]=,num[][]=,num[][]=;
while(x)
{
if(x&) mer(num,a);
mer(a,a);
x>>=;
}
}
void cal(long long sum[],long long s[][])
{
long long x=(sum[]*s[][]%mod+sum[]*s[][]%mod)%mod;
long long y=(sum[]*s[][]%mod+sum[]*s[][]%mod)%mod;
sum[]=x,sum[]=y;
}
void pushdown(int k)
{
if(add[k][][]==&&add[k][][]==&&add[k][][]==&&add[k][][]==) return;
//printf("A");
//cal(sum[k],add[k]);
int l=ch[k][],r=ch[k][];
if(l) mer(add[l],add[k]),cal(sum[l],add[k]);
if(r) mer(add[r],add[k]),cal(sum[r],add[k]);
add[k][][]=,add[k][][]=,add[k][][]=,add[k][][]=;
}
void update(int k)
{
int l=ch[k][],r=ch[k][];
//cal(sum[k],add[k]);
//pushdown(k);
for(int i=;i<;++i) sum[k][i]=(sum[l][i]+sum[r][i])%mod;
// if(k==2) printf("A : %d %d %lld %lld\n",l,r,sum[l][0],sum[r][0]);
}
int build(int l,int r)
{
if(l>r) return ;
int mid=(l+r)>>;
int k=++len;
add[k][][]=,add[k][][]=,add[k][][]=,add[k][][]=;
if(l==r)
{
sum[k][]=,sum[k][]=;
long long num[][];
fib(num,a[l]-);
cal(sum[k],num);
//printf("%d %d %d %d %d\n",l,r,k,ch[k][0],ch[k][1]);
return k;
}
ch[k][]=build(l,mid);
ch[k][]=build(mid+,r);
update(k);
return k;
// printf("%d %d %d %d %d\n",l,r,k,ch[k][0],ch[k][1]);
}
void make(int k,int l,int r,int x,int y,long long num[][])
{
if(l>r) return;
if(l>y||r<x) return;
if(x<=l&&y>=r)
{
mer(add[k],num);
cal(sum[k],num);
return;
}
int mid=(l+r)>>;
pushdown(k);
if(l<=mid) make(ch[k][],l,mid,x,y,num);
if(r>mid) make(ch[k][],mid+,r,x,y,num);
update(k);
}
long long query(int k,int l,int r,int x,int y)
{
if(l>r) return ;
if(l>y||r<x) return ;
if(x<=l&&y>=r)
{
return sum[k][];
}
int mid=(l+r)>>;
pushdown(k);
return (query(ch[k][],l,mid,x,y)+query(ch[k][],mid+,r,x,y))%mod;
}
int main()
{ scanf("%d %d",&n,&m);
for(int i=;i<=n;++i) scanf("%lld",&a[i]);
build(,n);
//for(int i=1;i<=len;++i) printf("%d %lld %lld\n",i,sum[i][0],sum[i][1]);
//or(int i=1;i<=len;++i) printf("%d %lld %lld %lld %lld\n",i,add[i][0][0],add[i][0][1],add[i][1][0],add[i][1][1]);
for(int i=;i<=m;++i)
{
int t,l,r;
long long x;
scanf("%d %d %d",&t,&l,&r);
if(t==)
{
scanf("%lld",&x);
long long num[][];
fib(num,x);
make(,,n,l,r,num);
}
else printf("%lld\n",query(,,n,l,r));
}
return ;
}

CF719E(线段树+矩阵快速幂)的更多相关文章

  1. Wannafly Winter Camp 2019.Day 8 div1 E.Souls-like Game(线段树 矩阵快速幂)

    题目链接 \(998244353\)写成\(99824435\)然后调这个线段树模板1.5h= = 以后要注意常量啊啊啊 \(Description\) 每个位置有一个\(3\times3\)的矩阵, ...

  2. 线段树+矩阵快速幂 Codeforces Round #373 (Div. 2) E

    http://codeforces.com/contest/719/problem/E 题目大意:给你一串数组a,a[i]表示第i个斐波那契数列,有如下操作 ①对[l,r]区间+一个val ②求出[l ...

  3. CF575A Fibonotci [线段树+矩阵快速幂]

    题意 \(s\{\}\) 是一个循环数列 循环节为 \(n\),你可以改掉 \(m\) 项,这 \(m\) 项独立,且不影响循环节 考虑线段树维护矩阵,单点修改最多m次,每次矩阵快速幂就完事了 // ...

  4. Codeforces 719E [斐波那契区间操作][矩阵快速幂][线段树区间更新]

    /* 题意:给定一个长度为n的序列a. 两种操作: 1.给定区间l r 加上某个数x. 2.查询区间l r sigma(fib(ai)) fib代表斐波那契数列. 思路: 1.矩阵操作,由矩阵快速幂求 ...

  5. 【66测试20161115】【树】【DP_LIS】【SPFA】【同余最短路】【递推】【矩阵快速幂】

    还有3天,今天考试又崩了.状态还没有调整过来... 第一题:小L的二叉树 勤奋又善于思考的小L接触了信息学竞赛,开始的学习十分顺利.但是,小L对数据结构的掌握实在十分渣渣.所以,小L当时卡在了二叉树. ...

  6. 【XSY2524】唯一神 状压DP 矩阵快速幂 FFT

    题目大意 给你一个网格,每个格子有概率是\(1\)或是\(0\).告诉你每个点是\(0\)的概率,求\(1\)的连通块个数\(\bmod d=0\)的概率. 最开始所有格子的概率相等.有\(q\)次修 ...

  7. 培训补坑(day10:双指针扫描+矩阵快速幂)

    这是一个神奇的课题,其实我觉得用一个词来形容这个算法挺合适的:暴力. 是啊,就是循环+暴力.没什么难的... 先来看一道裸题. 那么对于这道题,显然我们的暴力算法就是枚举区间的左右端点,然后通过前缀和 ...

  8. 【对不同形式矩阵的总结】WC 2009 最短路径问题(线段树+矩阵乘法)

    题意 ​ 题目链接:https://www.luogu.org/problem/P4150 ​ 一个 \(6\times n\) 的网格图,每个格点有一个初始权值.有两种操作: 修改一个格子的权值 求 ...

  9. 【模板】矩阵快速幂 洛谷P2233 [HNOI2002]公交车路线

    P2233 [HNOI2002]公交车路线 题目背景 在长沙城新建的环城公路上一共有8个公交站,分别为A.B.C.D.E.F.G.H.公共汽车只能够在相邻的两个公交站之间运行,因此你从某一个公交站到另 ...

随机推荐

  1. CSS笔记总结

    1.让页面里的字体变清晰和变细 -webkit-font-smoothing: antialiased; 2.让Chrome支持小于12px 的文字 -webkit-text-size-adjust: ...

  2. jquery获取table的行数、列数

    $("#grd").find("tr").length; //行数 $("#grd").find("tr").find( ...

  3. [下载]北京新版小学英语五年级上册mp3点读APP

    义务教育教科书小学英语五年级上册点读软件.根据2014年北京教改版教材编写,发音标准.实现点读功能.点到哪里读到哪里.哪里不会点哪里!北京教育科学研究院编写,北京出版社出版.ISBN:97872001 ...

  4. α-β剪枝算法的java语言实现(非常实用)

    利用α-β剪枝算法,对下图所示的博弈树进行搜索,搜索得到根节点选择的走步,以及没有必要进行评估的节点,并求出给出在何处发生了剪枝,以及剪枝的类型(属于α剪枝还是β剪枝). 注:□表示MIN节点:○表示 ...

  5. java访问修饰符

    了解面向对象思想的同学们,都知道"封装"这一基本特征,如何正确运用访问修饰符,恰恰能体现出封装的好坏. java访问修饰符有四个: 1)public:访问权限最高,其修饰的类.类变 ...

  6. 如何在SpringBoot中使用JSP ?但强烈不推荐,果断改Themeleaf吧

    做WEB项目,一定都用过JSP这个大牌.Spring MVC里面也可以很方便的将JSP与一个View关联起来,使用还是非常方便的.当你从一个传统的Spring MVC项目转入一个Spring Boot ...

  7. 【夯实PHP基础】php开发时遇到白页的调试方法

    本文地址   分享提纲: 1. 设置报错报错级别,显示报错 2. 白页的可能原因     1.[设置报错报错级别,显示报错] php开发时,访问地址也对,但就是不出来页面,显示的是 白的页面,所以就可 ...

  8. elasticsearch高级配置二----线程池设置

    一个Elasticsearch节点会有多个线程池,但重要的是下面四个: 索引(index):主要是索引数据和删除数据操作(默认是cached类型) 搜索(search):主要是获取,统计和搜索操作(默 ...

  9. jsPanel插件Option总结

    jsPanel插件Option总结 学习jsPanel之余对相关的选项进行了总结,便于参考. # 选项名称 类别 简要说明 1 autoclose configuration 设置一个时间在毫秒后,面 ...

  10. CssStats – 分析和优化网站 CSS 代码的利器

    CssStats 是一个在线的 CSS 代码分析工具,你只需要输入网址或者直接 CSS 地址即可进行 CSS 代码的全方位分析,是前端开发人员和网页设计师分析网站 CSS 代码的利器,可以统计出 CS ...