河南省多校联盟二-F 线段树+矩阵
---恢复内容开始---
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的题目,有趣在维护节点时用到了矩阵运算,减少了计算量。
首先对于矩阵运算法则,百度百科:
基本性质
- 乘法结合律: (AB)C=A(BC).[2]
- 乘法左分配律:(A+B)C=AC+BC[2]
- 乘法右分配律:C(A+B)=CA+CB[2]
- 对数乘的结合性k(AB)=(kA)B=A(kB).
- 转置 (AB)T=BTAT.
- 矩阵乘法一般不满足交换律[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 线段树+矩阵的更多相关文章
- 河南省多校联盟二-C
1281: 邪能炸弹 时间限制: 1 秒 内存限制: 128 MB提交: 222 解决: 80 题目描述 正在入侵艾泽拉斯的古尔丹偶然间得到了一颗邪能炸弹,经过研究,他发现这是一颗威力极其巨大且难 ...
- 河南省多校联盟二-A
1279: 简单的背包问题 时间限制: 1 秒 内存限制: 32 MB提交: 361 解决: 20 题目描述 相信大家都学过背包问题了吧,那么现在我就考大家一个问题.有n个物品,每个物品有它的重量 ...
- POJ2155 Matrix二维线段树经典题
题目链接 二维树状数组 #include<iostream> #include<math.h> #include<algorithm> #include<st ...
- POJ2155Matrix(二维线段树)
链接http://poj.org/problem?id=2155 题目操作就是说,每次操作可以是编辑某个矩形区域,这个区域的0改为1,1改为0,每次查询只查询某一个点的值是0还是1. 方法:二维线段树 ...
- codeforces 677D D. Vanya and Treasure(二维线段树)
题目链接: D. Vanya and Treasure time limit per test 1.5 seconds memory limit per test 256 megabytes inpu ...
- Luck and Love(二维线段树)
Luck and Love Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- [JZOJ3615]【NOI2014模拟】数列(平面几何+二维线段树)
Description 给定一个长度为n的正整数数列a[i]. 定义2个位置的f值为两者位置差与数值差的和,即f(x,y)=|x-y|+|a[x]-a[y]|. 你需要写一个程序支持2种操作(k都是正 ...
- 「ZJOI2017」树状数组(二维线段树)
「ZJOI2017」树状数组(二维线段树) 吉老师的题目真是难想... 代码中求的是 \(\sum_{i=l-1}^{r-1}a_i\),而实际求的是 \(\sum_{i=l}^{r}a_i\),所以 ...
- BZOJ2877 NOI2012魔幻棋盘(二维线段树)
显然一个序列的gcd=gcd(其差分序列的gcd,序列中第一个数).于是一维情况直接线段树维护差分序列即可. 容易想到将该做法拓展到二维.于是考虑维护二维差分,查询时对差分矩阵求矩形的gcd,再对矩形 ...
随机推荐
- robotFramework_ride_python2_Wxpython测试环境搭建
(提示:我的安装版本是robotFramework3.0+ride1.5+python2.7+wxpython2.8,至于wxpython3.0下ride安装打不开的问题我还没找到原因,建议刚开始先不 ...
- Activity 间 bundle 传递参数
activity_main.xml <TableLayout xmlns:android="http://schemas.android.com/apk/res/android&quo ...
- LINQ查询中的IEnumerable<T>和IQueryable<T>
LINQ查询方法一共提供了两种扩展方法,在System.Linq命名空间下,有两个静态类:Enumerable类,它针对继承了IEnumerable<T>接口的集合进行扩展:Queryab ...
- hihocoder1478 水陆距离
地址:http://hihocoder.com/problemset/problem/1478 题目: 水陆距离 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个 ...
- 安卓 和 IOS 的icon 尺寸
安卓 36*36 48*48 72*72 96*96 IOS Icon.png – 57×57 iPhone (ios5/6) Icon@2x.png – 114×114 iPhone Retina ...
- fir.im 测试包下载工具--FIRReader 的图文介绍
fir.im 是一个供开发者上传测试包(也可以是企业的正式包)的网站.该网站提供了接口访问应用资源.下面要介绍的这个应用对接了这些接口,供用户方便下载应用. 先来看下应用截图吧! 主要有以下功能点:1 ...
- Java linkedList详细介绍及使用示例
①LinkedList简单介绍 是一个继承于AbstractSequentialList的双向链表.它可以被当成堆栈.队列或双端队列进行操作. 实现了List接口,能对它进行队列操作. 实现了Dequ ...
- MVP架构学习
MVP架构学习 M:数据层(数据库,文件,网络等...) V:UI层(Activity,Fragment,View以及子类,Adapter以及子类) P:中介,关联UI层和数据层,因为V和M是相互看不 ...
- sublime 安装插件报错
sublime 安装插件报错,大部分原因是本地防火墙开启了,关闭本地防火墙
- sift算法特征点如何匹配?
https://www.zhihu.com/question/23371175 我需要把一张照片和训练集中的图片进行匹配.我把一张照片提取特征值并建立kd树,然后把训练集的图片依次读进来,然后把图片的 ...