---恢复内容开始---

1284: SP教数学

时间限制: 2 秒  内存限制: 128 MB
提交: 24  解决: 4

题目描述

输入

输出

对于每组数据的2操作,输出一行对1e9 + 7取模的答案

样例输入

7 4
2 2 1 1 3 3 2
2 1 5
2 6 7
1 3 4 3
2 6 6

样例输出

6
3
2

提示

1 <=  n ,m <=10^5

一道很有趣的ST的题目,有趣在维护节点时用到了矩阵运算,减少了计算量。

首先对于矩阵运算法则,百度百科:

基本性质

  1. 乘法结合律: (AB)C=A(BC).[2] 
  2. 乘法左分配律:(A+B)C=AC+BC[2] 
  3. 乘法右分配律:C(A+B)=CA+CB[2] 
  4. 对数乘的结合性k(AB)=(kA)B=A(kB).
  5. 转置 (AB)T=BTAT
  6. 矩阵乘法一般不满足交换律[3] 

题目的重点是如何快速求出∑ri=l f(i) , 其中f(i)表示第i个斐波那契数,(f1=f2=1)

这里的i会更新,+x操作,那么如何快速的计算这个值呢,一项一项利用快速幂? len*log(n)的复杂度难免有些太高了。

我们可以利用当前已知的区间和和增量一次性计算得到新的区间和,这里用到一些公式。

假设当前区间有三个元素 [a,b,c] ,s1=fa+fb+fc  增量为x,

-->[a+x,b+x,c+x] ,  s2=f(a+x)+f(b+x),f(c+x);

由矩阵关于斐波那契的递推式有:(fn,fn-1)=(fn-1,fn-2)*(1 01 1)    //请自行脑补对齐= =

-->(f(a+x),f(a+x-1))=(f(a),f(a-1))*(1 01 1)^x

(f(b+x),f(b+x-1))=(f(b),f(b-1))*(1 01 1)^x

(f(c+x),f(c+x-1))=(f(c),f(c-1))*(1 01 1)^x

将三个等式相加得到 (s2,f(a+x-1)+f(b+x-1)+f(c+x-1))=(s1,f(a-1)+f(b-1)+f(c-1))*(1 01 1)^x  //由于矩阵运算满足单向的分配律

我们已经找到了s2和s1的关系了,在已知x和行矩阵的第二个元素的情况下,只需要对(1 01 1)进行一次矩阵幂便可得到s2.

由于计算时必须要知道行矩阵的第二项,我们不妨对于每个节点维护两个值,是Σri=l f(i) 和  Σri=l f(i-1),利用laz标记的x便可快速的完成释放操作。

 #include<bits/stdc++.h>
using namespace std;
#define LL long long
LL MOD=1e9+;
const LL MAXN=(<<)+;
struct Matrix
{
int r=,w=;
LL a[][];
void init(){memset(a,,sizeof(a));}
Matrix operator*(const Matrix &tmp){
Matrix ans;
ans.r=r;ans.w=tmp.w;
ans.init();
for(int i=;i<=r;++i)
for(int k=;k<=w;++k)
for(int j=;j<=tmp.w;++j)
ans.a[i][j]=(ans.a[i][j]+a[i][k]*tmp.a[k][j])%MOD;
return ans;
}
Matrix operator+(const Matrix &tmp){
Matrix ans;
ans.r=r;ans.w=w;
ans.init();
for(int i=;i<=r;++i)
for(int j=;j<=w;++j)
ans.a[i][j]=(ans.a[i][j]+a[i][j]+tmp.a[i][j])%MOD;
return ans;
}
}unit,Am;
void init()
{
unit.init();unit.r=unit.w=;
for(int i=;i<=;++i) unit.a[i][i]=;
Am.init(),Am.r=Am.w=;
Am.a[][]=Am.a[][]=Am.a[][]=;
}
Matrix qpow(Matrix A,LL n)
{
Matrix ans=unit;
ans.r=A.r;
ans.w=A.w;
while(n){
if(n&) ans=ans*A;
A=A*A;
n>>=;
}
return ans;
}
struct node
{
LL x,y;
};
struct Segtree
{
#define M ((L+R)>>1)
#define lc (id<<1)
#define rc (id<<1|1)
LL laz[MAXN];
node sum[MAXN];
void init()
{
memset(laz,,sizeof(laz));
memset(sum,,sizeof(sum));
}
void build(int L,int R,int id)
{
if(L==R){
LL x; scanf("%lld",&x);
if(x==){sum[id].x=;}
else if(x==) {sum[id].x=sum[id].y=;}
else{
Matrix t=qpow(Am,x-);
sum[id].x=(t.a[][]+t.a[][])%MOD;
sum[id].y=(t.a[][]+t.a[][])%MOD;
// cout<<sum[id].x<<" "<<sum[id].y<<endl;
}
return;
}
build(L,M,lc);
build(M+,R,rc);
pushup(L,R,id);
}
void pushdown(int L,int R,int id)
{
if(!laz[id]) return;
laz[lc]+=laz[id];
laz[rc]+=laz[id];
Matrix t=qpow(Am,laz[id]);
LL x1=sum[lc].x,y1=sum[lc].y;
sum[lc].x=(x1*t.a[][]%MOD+y1*t.a[][]%MOD)%MOD;
sum[lc].y=(x1*t.a[][]%MOD+y1*t.a[][]%MOD)%MOD;
x1=sum[rc].x,y1=sum[rc].y;
sum[rc].x=(x1*t.a[][]%MOD+y1*t.a[][]%MOD)%MOD;
sum[rc].y=(x1*t.a[][]%MOD+y1*t.a[][]%MOD)%MOD;
laz[id]=;
}
void pushup(int L,int R,int id)
{
sum[id].x=(sum[lc].x+sum[rc].x)%MOD;
sum[id].y=(sum[lc].y+sum[rc].y)%MOD;
}
void update(int L,int R,int id,int l,int r,LL v)
{
if(L>=l&&R<=r){
laz[id]+=v;
Matrix t=qpow(Am,v);
LL x1=sum[id].x,y1=sum[id].y;
sum[id].x=(x1*t.a[][]%MOD+y1*t.a[][]%MOD)%MOD;
sum[id].y=(x1*t.a[][]%MOD+y1*t.a[][]%MOD)%MOD;
return;
}
pushdown(L,R,id);
if(l<=M) update(L,M,lc,l,r,v);
if(r>M) update(M+,R,rc,l,r,v);
pushup(L,R,id);
}
LL ask(int L,int R,int id,int l,int r)
{
if(L>=l&&R<=r) return sum[id].x%MOD;
pushdown(L,R,id);
LL s=;
if(l<=M) s=(s+ask(L,M,lc,l,r))%MOD;
if(r>M) s=(s+ask(M+,R,rc,l,r))%MOD;
pushup(L,R,id);
return s;
}
}seg;
int main()
{
init();
LL n,m,x,a;
int i,opt,j,l,r,k;
while(cin>>n>>m){
seg.init();
seg.build(,n,);
for(i=;i<=m;++i){
cin>>opt;
LL v;
if(opt==){
cin>>l>>r>>v;
seg.update(,n,,l,r,v);
}
else{
cin>>l>>r;
cout<<seg.ask(,n,,l,r)<<endl;
}
}
}
return ;
}

1284: SP教数学

时间限制: 2 秒  内存限制: 128 MB
提交: 24  解决: 4

题目描述

输入

---恢复内容结束---

河南省多校联盟二-F 线段树+矩阵的更多相关文章

  1. 河南省多校联盟二-C

    1281: 邪能炸弹 时间限制: 1 秒  内存限制: 128 MB提交: 222  解决: 80 题目描述 正在入侵艾泽拉斯的古尔丹偶然间得到了一颗邪能炸弹,经过研究,他发现这是一颗威力极其巨大且难 ...

  2. 河南省多校联盟二-A

    1279: 简单的背包问题 时间限制: 1 秒  内存限制: 32 MB提交: 361  解决: 20 题目描述 相信大家都学过背包问题了吧,那么现在我就考大家一个问题.有n个物品,每个物品有它的重量 ...

  3. POJ2155 Matrix二维线段树经典题

    题目链接 二维树状数组 #include<iostream> #include<math.h> #include<algorithm> #include<st ...

  4. POJ2155Matrix(二维线段树)

    链接http://poj.org/problem?id=2155 题目操作就是说,每次操作可以是编辑某个矩形区域,这个区域的0改为1,1改为0,每次查询只查询某一个点的值是0还是1. 方法:二维线段树 ...

  5. codeforces 677D D. Vanya and Treasure(二维线段树)

    题目链接: D. Vanya and Treasure time limit per test 1.5 seconds memory limit per test 256 megabytes inpu ...

  6. Luck and Love(二维线段树)

    Luck and Love Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...

  7. [JZOJ3615]【NOI2014模拟】数列(平面几何+二维线段树)

    Description 给定一个长度为n的正整数数列a[i]. 定义2个位置的f值为两者位置差与数值差的和,即f(x,y)=|x-y|+|a[x]-a[y]|. 你需要写一个程序支持2种操作(k都是正 ...

  8. 「ZJOI2017」树状数组(二维线段树)

    「ZJOI2017」树状数组(二维线段树) 吉老师的题目真是难想... 代码中求的是 \(\sum_{i=l-1}^{r-1}a_i\),而实际求的是 \(\sum_{i=l}^{r}a_i\),所以 ...

  9. BZOJ2877 NOI2012魔幻棋盘(二维线段树)

    显然一个序列的gcd=gcd(其差分序列的gcd,序列中第一个数).于是一维情况直接线段树维护差分序列即可. 容易想到将该做法拓展到二维.于是考虑维护二维差分,查询时对差分矩阵求矩形的gcd,再对矩形 ...

随机推荐

  1. HDU 1114 Piggy-Bank(完全背包模板题)

    完全背包模板题 #include<cstdio> #include<cstring> #include<algorithm> using namespace std ...

  2. ACM-ICPC 2018 南京赛区网络预赛 G. Lpl and Energy-saving Lamps (弱线段树)

    线段树节点维护区间最小值,查找时优先从左侧的区间寻找. 每一次循环都在树中不停寻找第一个小于等于当前持有数的值,然后抹去,直到找不到为止. #include<cstdio> #includ ...

  3. Docker+.Net Core 的那些事儿-1.准备工作

    1.下载centos 地址:https://www.centos.org/download/ 我使用的是DVD ISO,这么做的目的是为了在之后的docker填坑的路上,方便使用centos中Fire ...

  4. JS监听checkbox的选择获取取消事件代码案列

    function OncheckBox(index){ if ($(index).attr("checked") == "checked") { alert($ ...

  5. FFmpeg从入门到精通——进阶篇,SEI那些事儿

    前言 在直播应用的开发过程中,如果把主播端消息事件传递到观众端,一般会以Instant Messaging(即时通讯)的方式传递过去,但因为消息分发通道和直播通道是分开的,因此消息与直播音视频数据的同 ...

  6. RabbitMQ学习之(三)_Centos6下RabbitMQ PHP扩展的安装

    安装rabbitmq-c依赖包 yum install libtool autoconf 下载安装rabbitmq-c wget https://github.com/alanxz/rabbitmq- ...

  7. 北京电子科技学院(BESTI)实验报告2

    北京电子科技学院(BESTI)实验报告2 课程: 信息安全系统设计基础 班级:1452.1453 姓名:(按贡献大小排名)郑凯杰 .周恩德 学号:(按贡献大小排名)20145314 .20145217 ...

  8. 20145328 《Java程序设计》第5周学习总结

    20145328 <Java程序设计>第5周学习总结 教材学习内容总结 语法和继承架构 异常处理关键字 第八章内容主要是对Java的异常处理 Java的异常处理是通过5个关键字来实现的:t ...

  9. CentOS安装wkhtmltopdf及解决中文支持问题

    安装wkhtmltopdf,先下载  wkhtmltox-0.12.2.1_linux-centos6-amd64.rpm yum install -y wkhtmltox-0.12.2.1_linu ...

  10. springboot集成shiro 前后端分离 统一处理shiro异常

    在前后端分离的情况下,shiro一些权限异常处理会返回401之类的结果,这种结果不好统一管理.我们希望的结果是统一管理,所有情况都受我们控制 就算权限验证失败,我们也希望返回200,并且返回我们定义的 ...