【Codeforces 718C&719E】Sasha and Array【线段树成段更新+矩阵快速幂】
2016-10-04 16:57
453 查看
题意:
给你一个数列,有两种操作1 l r x 给[l,r]区间上的数加上x, 2 l r 询问[l,r]区间fibonacci数列的和(f[l]+f[l+1]+……f[r])
题解:
这样的区间加和区间询问很容易想到线段树成段更新,关键是怎么存储信息,我们都知道fibonacci数列可以用矩阵快速幂递推,基础矩阵是a[0][0]=1,a[0][1]=1,a[1][0]=1,a[1][1]=0,a[0][0]中存储的就是当前的fibonacci值(不会这个可以先做下poj3070)
然后我们可以在线段树的每个节点都存一个2*2的矩阵,这个矩阵就是当前fibonacci数列的运算矩阵,这是线段树的建树过程,
现在我们来看操作1 [l,r]区间上的数加上x 我们设A[x]矩阵代表基础矩阵乘上x次之后形成的矩阵(这里提下在上一条建树操作的时候数值为1的矩阵应该是单位矩阵,数值y大于等于1的存的应该是A[y-1]) 给区间数加上x就相当于给区间所有矩阵乘上一个A[x] 也即A[x]*(A[l]+A[l+1]+……+A[r]) 这样1操作可以用lazy的思想直接对整段进行更新
然后看操作2 我们只要对[l,r]中存的矩阵中[0][0]位置的数求和就是答案
注意:
线段树操作时所有的lazy,sum都用2*2的矩阵来存,并且lazy操作时矩阵是相乘而不是想加(本人在这儿错了好久)
给你一个数列,有两种操作1 l r x 给[l,r]区间上的数加上x, 2 l r 询问[l,r]区间fibonacci数列的和(f[l]+f[l+1]+……f[r])
题解:
这样的区间加和区间询问很容易想到线段树成段更新,关键是怎么存储信息,我们都知道fibonacci数列可以用矩阵快速幂递推,基础矩阵是a[0][0]=1,a[0][1]=1,a[1][0]=1,a[1][1]=0,a[0][0]中存储的就是当前的fibonacci值(不会这个可以先做下poj3070)
然后我们可以在线段树的每个节点都存一个2*2的矩阵,这个矩阵就是当前fibonacci数列的运算矩阵,这是线段树的建树过程,
现在我们来看操作1 [l,r]区间上的数加上x 我们设A[x]矩阵代表基础矩阵乘上x次之后形成的矩阵(这里提下在上一条建树操作的时候数值为1的矩阵应该是单位矩阵,数值y大于等于1的存的应该是A[y-1]) 给区间数加上x就相当于给区间所有矩阵乘上一个A[x] 也即A[x]*(A[l]+A[l+1]+……+A[r]) 这样1操作可以用lazy的思想直接对整段进行更新
然后看操作2 我们只要对[l,r]中存的矩阵中[0][0]位置的数求和就是答案
注意:
线段树操作时所有的lazy,sum都用2*2的矩阵来存,并且lazy操作时矩阵是相乘而不是想加(本人在这儿错了好久)
#include<map> #include<cmath> #include<stack> #include<queue> #include<bitset> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define PB push_back #define MP make_pair #define ll __int64 #define MS(a,b) memset(a,b,sizeof(a)) #define LL (rt<<1) #define RR (rt<<1|1) #define lson l,mid,LL #define rson mid+1,r,RR #define pii pair<int,int> #define pll pair<ll,ll> #define lb(x) (x&(-x)) using namespace std; void In(){freopen("in.in","r",stdin);} void Out(){freopen("out.out","w",stdout);} const int N=1e5+10; const int M=1e6+10; const int Mbit=1e6+10; const int inf=0x3f3f3f3f; const ll mod=1e9+7; struct Matrix { ll mat[2][2]; int n; Matrix(){} Matrix(int _n) { n=_n; for(int i=0;i<n;i++)for(int j=0;j<n;j++)mat[i][j]=0; } void zero(int _n) { n=_n; for(int i=0;i<n;i++)for(int j=0;j<n;j++)mat[i][j]=0; } void unit(int _n) { n=_n; for(int i=0;i<n;i++)for(int j=0;j<n;j++)mat[i][j]=(i==j); } Matrix operator +(const Matrix &b)const { Matrix ret=Matrix(n); for(int i=0;i<n;i++) for(int j=0;j<n;j++) ret.mat[i][j]=(mat[i][j]+b.mat[i][j])%mod; return ret; } Matrix operator *(const Matrix &b)const { Matrix ret = Matrix(n); for(int i=0;i<n;i++) for(int j=0;j<n;j++) for(int k=0;k<n;k++) (ret.mat[i][j]+=mat[i][k]*b.mat[k][j])%=mod; return ret; } }; Matrix mul(Matrix s,int n) { Matrix ans; ans.unit(s.n); while(n){ if(n&1)ans=ans*s; s=s*s; n>>=1; } return ans; } struct node { Matrix lazy,sum; bool flag; }tree[N<<2]; Matrix fibo(int x) { Matrix s; s.n=2; s.mat[0][0]=1;s.mat[0][1]=1; s.mat[1][0]=1;s.mat[1][1]=0; return mul(s,x-1); } Matrix fibo1(int x) { Matrix s; s.n=2; s.mat[0][0]=1;s.mat[0][1]=1; s.mat[1][0]=1;s.mat[1][1]=0; return mul(s,x); } void up(int rt) { tree[rt].sum=tree[LL].sum+tree[RR].sum; } void down(int rt) { if(tree[rt].flag){ tree[LL].lazy=tree[LL].lazy*tree[rt].lazy; tree[RR].lazy=tree[RR].lazy*tree[rt].lazy; tree[LL].sum=tree[LL].sum*tree[rt].lazy; tree[RR].sum=tree[RR].sum*tree[rt].lazy; tree[LL].flag=tree[RR].flag=1; tree[rt].flag=0;tree[rt].lazy.unit(2); } } void build(int l,int r,int rt) { if(l==r){ int x;scanf("%d",&x); tree[rt].sum=fibo(x); tree[rt].lazy.unit(2); tree[rt].flag=0; return; } tree[rt].sum.zero(2); tree[rt].lazy.unit(2); tree[rt].flag=0; int mid=(l+r)>>1; build(lson); build(rson); up(rt); } void update(int L,int R,int l,int r,int rt,Matrix x) { if(L<=l&&r<=R){ tree[rt].lazy=tree[rt].lazy*x; tree[rt].flag=1; tree[rt].sum=tree[rt].sum*x; return; } down(rt); int mid=(l+r)/2; if(L<=mid) update(L,R,lson,x); if(R>mid) update(L,R,rson,x); up(rt); } ll query(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R)return tree[rt].sum.mat[0][0]; int mid=(l+r)/2; down(rt); ll ans=0; if(L<=mid)ans+=query(L,R,lson); if(R>mid) ans+=query(L,R,rson); up(rt); return ans%mod; } int main() { int n,m,op,l,r,x; while(~scanf("%d%d",&n,&m)){ build(1,n,1); while(m--){ scanf("%d%d%d",&op,&l,&r); if(op==1){ scanf("%d",&x); update(l,r,1,n,1,fibo(1+x)); } else printf("%I64d\n",query(l,r,1,n,1)); } } return 0; }
相关文章推荐
- [Codeforces 719 E. Sasha and Array] 矩阵快速幂+线段树
- codeforces 373div1 Sasha and Array 矩阵+线段树
- Codeforces Round #373 (Div. 2) E. Sasha and Array 矩阵快速幂+线段树
- Codeforces 718C Sasha and Array(线段树维护矩阵)
- 【codeforces 719E】Sasha and Array
- 【CodeForces 719E】【线段树+矩阵快速幂】 Sasha and Array
- 线段树维护矩阵【CF718C】 Sasha and Array
- Codeforces Round #373 (Div. 2) E. Sasha and Array 线段树维护矩阵
- Codeforces Round #373 (Div. 2) E. Sasha and Array 线段树维护矩阵
- 【codeforces 718 C&D】C. Sasha and Array&D. Andrew and Chemistry
- Codeforces 719E [斐波那契区间操作][矩阵快速幂][线段树区间更新]
- [题解]codeforces 718c Sasha and Array
- Codeforces 450B-Jzzhu and Sequences (矩阵快速幂)
- CodeForces 719E Sasha and Array 【线段树】【快速矩阵幂】
- CodeForces 718C Sasha and Array
- Mayor's posters----POJ_2528----线段树之成段更新and离散化
- “盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛题解&&源码【A,水,B,水,C,水,D,快速幂,E,优先队列,F,暴力,G,贪心+排序,H,STL乱搞,I,尼姆博弈,J,差分dp,K,二分+排序,L,矩阵快速幂,M,线段树区间更新+Lazy思想,N,超级快速幂+扩展欧里几德,O,BFS】
- Codeforces 514E. Darth Vader and Tree DP+矩阵快速幂
- codeforces 315 B.Sereja and Array(线段树区间更新+单点更新+单点询问)
- 线段树 CodeForces 220B - Little Elephant and Array