CF719E(线段树+矩阵快速幂)
题意:给你一个数列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(线段树+矩阵快速幂)的更多相关文章
- Wannafly Winter Camp 2019.Day 8 div1 E.Souls-like Game(线段树 矩阵快速幂)
题目链接 \(998244353\)写成\(99824435\)然后调这个线段树模板1.5h= = 以后要注意常量啊啊啊 \(Description\) 每个位置有一个\(3\times3\)的矩阵, ...
- 线段树+矩阵快速幂 Codeforces Round #373 (Div. 2) E
http://codeforces.com/contest/719/problem/E 题目大意:给你一串数组a,a[i]表示第i个斐波那契数列,有如下操作 ①对[l,r]区间+一个val ②求出[l ...
- CF575A Fibonotci [线段树+矩阵快速幂]
题意 \(s\{\}\) 是一个循环数列 循环节为 \(n\),你可以改掉 \(m\) 项,这 \(m\) 项独立,且不影响循环节 考虑线段树维护矩阵,单点修改最多m次,每次矩阵快速幂就完事了 // ...
- Codeforces 719E [斐波那契区间操作][矩阵快速幂][线段树区间更新]
/* 题意:给定一个长度为n的序列a. 两种操作: 1.给定区间l r 加上某个数x. 2.查询区间l r sigma(fib(ai)) fib代表斐波那契数列. 思路: 1.矩阵操作,由矩阵快速幂求 ...
- 【66测试20161115】【树】【DP_LIS】【SPFA】【同余最短路】【递推】【矩阵快速幂】
还有3天,今天考试又崩了.状态还没有调整过来... 第一题:小L的二叉树 勤奋又善于思考的小L接触了信息学竞赛,开始的学习十分顺利.但是,小L对数据结构的掌握实在十分渣渣.所以,小L当时卡在了二叉树. ...
- 【XSY2524】唯一神 状压DP 矩阵快速幂 FFT
题目大意 给你一个网格,每个格子有概率是\(1\)或是\(0\).告诉你每个点是\(0\)的概率,求\(1\)的连通块个数\(\bmod d=0\)的概率. 最开始所有格子的概率相等.有\(q\)次修 ...
- 培训补坑(day10:双指针扫描+矩阵快速幂)
这是一个神奇的课题,其实我觉得用一个词来形容这个算法挺合适的:暴力. 是啊,就是循环+暴力.没什么难的... 先来看一道裸题. 那么对于这道题,显然我们的暴力算法就是枚举区间的左右端点,然后通过前缀和 ...
- 【对不同形式矩阵的总结】WC 2009 最短路径问题(线段树+矩阵乘法)
题意 题目链接:https://www.luogu.org/problem/P4150 一个 \(6\times n\) 的网格图,每个格点有一个初始权值.有两种操作: 修改一个格子的权值 求 ...
- 【模板】矩阵快速幂 洛谷P2233 [HNOI2002]公交车路线
P2233 [HNOI2002]公交车路线 题目背景 在长沙城新建的环城公路上一共有8个公交站,分别为A.B.C.D.E.F.G.H.公共汽车只能够在相邻的两个公交站之间运行,因此你从某一个公交站到另 ...
随机推荐
- domReady的实现
我们都知道JQ的 $(document).ready(fn) 方法.可以在页面准备就绪后才执行脚本,该方法相比传统的window.onload 事件,它的优势体现于onload事件是需要等到页面中所有 ...
- EntityFramework中的DbContext使用疑点说明
1.DbContext怎么在Asp.mvc中使用? public class Repository { //实例化EF容器:有弊端.一个线程里可能会创建多个DbContext //DbContext ...
- sql server left 和right 函数
参考文章:微信公众号文章 一直对sql中的left和right有误解,一直以为它是这样的. 执行这样一句: ) leftNum ) rightNum 出现的结果是这样的: 而我心中这样认为: 我认为只 ...
- 【无私分享:ASP.NET CORE 项目实战(第四章)】Code First 创建数据库和数据表
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 本章我们来介绍下Asp.net Core 使用 CodeFirst 创建数据库和表,通过 控制台 和 dotnet ef 两种 ...
- 浅谈Slick(3)- Slick201:从fp角度了解Slick
我在上期讨论里已经成功的创建了一个简单的Slick项目,然后又尝试使用了一些最基本的功能.Slick是一个FRM(Functional Relational Mapper),是为fp编程提供的scal ...
- spider RPC性能测试报告
测试环境部署结构 测试用例 类 别 说明 请求报文 194字节({"systemId":"PL","appVersion":"qq ...
- 设计模式02迭代器(java)
先贴代码,有空来写内容. 1.定义集合 import java.util.List; import java.util.ArrayList; //coollection是我自己定义的一个集合,因为要写 ...
- 怎样在asp中产生10个0-99的随机数
<% randomize for i=1 to 10 response.write cint(rnd*100) next %> randomize是随机初始化,使用rnd之前必须要先来一句 ...
- jQuery的案例及必知重要的jQuery选择器
Jquery能做什么 访问和操作DOM元素 控制页面样式 对页面事件进行处理 扩展新的jQuery插件 与Ajax技术完美结合 Jquery的优势 体积小,压缩后只有100KB左右 l强大的选择器 出 ...
- 【原】EasyUI ComboGrid 集成分页、按键示例
需求: 1.下拉框下拉时出现表格: 2.表格带分页功能: 3.可以使用向上键.向下键在表格中移动选择行数据: 4.可以使用回车键在表格中选中行数据: 5.在下拉框的文本框中输入内容,能查询表格: 6. ...