题意:给你一个数列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. 类型基础---CLR Via C#笔记一

    一.所有类型都是从System.Obejct派生 1.下面两个类型定义是完全一致的: class Employee{ ... } class Employee:System.Object{ ... } ...

  2. git 版本回退

    由于操作失误,需要将代码进行版本回退,首先在本地仓库执行了“git reset --hard HEAD^”命令,这样只会回退本地仓库的代码,但是我的代码之前已经push到了远程库中,查看远程仓库,发现 ...

  3. Jsp的九大对象,七大动作,三大指令

    jsp九大内置对象:1>out 向客户端输出数据,字节流.如out.print(" dgaweyr"); 2>request 接收客户端的http请求.String g ...

  4. 「译」JUnit 5 系列:架构体系

    原文地址:http://blog.codefx.org/design/architecture/junit-5-architecture/ 原文日期:29, Mar, 2016 译文首发:Linesh ...

  5. Spring MVC中文文档翻译发布

    前后经过九个月,我翻译的Spring MVC官方4.2.4版本中文文档可以发布第一个较为完整的版本了.译文上尽量做到准确并且符合中文习惯,让人能读懂,能理解.现全文发布如下,也希望它能够给出其价值,并 ...

  6. 【无私分享:ASP.NET CORE 项目实战(第六章)】读取配置文件(一) appsettings.json

    目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 在我们之前的Asp.net mvc 开发中,一提到配置文件,我们不由的想到 web.config 和 app.config,在 ...

  7. 同步辅助类CountDownLatch用法

    CountDownLatch是一个同步辅助类,犹如倒计时计数器,创建对象时通过构造方法设置初始值,调用CountDownLatch对象的await()方法则使当前线程处于等待状态,调用countDow ...

  8. 为什么applicationContext.xml和spring-servlet.xml中都有注解过滤<context:component-scan base-package="myproject"> 和<context:component-scan base-package="myproject.controller" />

    在刚学习SpringMVC框架整合时,你也许会产生疑问为什么Spring.xml和SpringMVC.xml中都有注解过滤. <context:component-scan base-packa ...

  9. GOF23设计模式之工厂模式

    -实现了创建者和调用者的分离 -面向对象设计的基本原则: ·OCP(开闭原则,Open-Closed Principle):一个软件的实体应当对扩展开放,对修改关闭 ·DIP(依赖倒转原则,Depen ...

  10. MAC远程连接服务器,不需要输入密码的配置方式

    cd ~/.ssh #没有则需要创建一个. mkdir ~/.ssh ssh-keygen -t rsa cd ~/.ssh scp id_rsa.pub root@IP地址:~/.ssh/id_rs ...