题解思路:
线段树维护,
用矩阵求斐波那契值,tree和lazy都要存成矩阵来降低时间复杂度
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<map>
#include<queue>
#include<stack>
#include<set>
#define lson l,mid,now<<1
#define rson mid+1,r,now<<1|1
#define ls now<<1
#define rs now<<1|1
#define all left,right,B,mod
#define ll long long
#define int long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=1e5+50;
using namespace std;
struct Matrix{
int nmap[3][3];
};
Matrix I=
{
1,0,0,
0,1,0,
0,0,1,
};
Matrix T=
{
0,0,0,
0,0,0,
0,0,0,
};
struct tree_node{
Matrix A;
}arr[maxn],tree[4*maxn],lazy[4*maxn];
void put(Matrix a)
{
for(int i=1;i<=2;i++)
{
for(int j=1;j<=2;j++)
{
cout<<a.nmap[i][j]<<" ";
}cout<<endl;
}
cout<<endl;
}
Matrix Matrix_mul(Matrix a,Matrix b,int mod)
{
Matrix A=T;
for(int k=1;k<=2;k++)
{
for(int i=1;i<=2;i++)
{
if(a.nmap[i][k])
for(int j=1;j<=2;j++)
{
A.nmap[i][j]+=(a.nmap[i][k]*b.nmap[k][j])%mod;
A.nmap[i][j]%=mod;
}
}
}
return A;
}
Matrix Matrix_s(Matrix a,int b,int mod)
{
Matrix A=I;
while(b)
{
if(b&1) A=Matrix_mul(A,a,mod);
a=Matrix_mul(a,a,mod);
b>>=1;
}
return A;
}
Matrix Matrix_add(Matrix a, Matrix b,int mod)
{
Matrix A=T;
A.nmap[1][1]=(a.nmap[1][1]+b.nmap[1][1])%mod;
A.nmap[2][1]=(a.nmap[2][1]+b.nmap[2][1])%mod;
return A;
}
void pushup(int now,int mod)
{
tree[now].A=Matrix_add(tree[ls].A,tree[rs].A,mod);
}
void built(int l,int r,int now,int mod)
{
int mid=(l+r)>>1;
lazy[now].A=I;
if(l==r)
{
tree[now].A=arr[l].A;
return ;
}
built(lson,mod);
built(rson,mod);
pushup(now,mod);
}
int cmp(Matrix a)
{
if(a.nmap[1][1]==1&&a.nmap[1][2]==0&&a.nmap[2][1]==0&&a.nmap[2][2]==1)
return 0;
return 1;
}
void pushdown(int now,int mod)
{
if(cmp(lazy[now].A))
{
lazy[rs].A=Matrix_mul(lazy[rs].A,lazy[now].A,mod);
lazy[ls].A=Matrix_mul(lazy[ls].A,lazy[now].A,mod);
tree[rs].A=Matrix_mul(lazy[now].A,tree[rs].A,mod);
tree[ls].A=Matrix_mul(lazy[now].A,tree[ls].A,mod);
lazy[now].A=I;
}
}
void updata(int l,int r,int now,int left,int right,Matrix B,int mod)
{
int mid=(l+r)>>1;
if(left<=l&&r<=right)
{
tree[now].A=Matrix_mul(B,tree[now].A,mod);
lazy[now].A=Matrix_mul(lazy[now].A,B,mod);
return ;
}
pushdown(now,mod);
if(left<=mid) updata(lson,all);
if(right>mid) updata(rson,all);
pushup(now,mod);
}
int query(int l,int r,int now,int left,int right,int mod)
{
int mid=(l+r)>>1;
if(left<=l&&r<=right)
{
return tree[now].A.nmap[1][1];
}
pushdown(now,mod);
int ans=0;
if(left<=mid) ans+=query(lson,left,right,mod);
if(right>mid) ans+=query(rson,left,right,mod);
return ans%mod;
}
#undef int
int main(){
#define int long long
Matrix B=
{
0,0,0,
0,0,1,
0,1,1,
};
Matrix A=
{
0,0,0,
0,0,0,
0,1,0,
};
int n,m,mod;
mod=1e9+7;
//cout<<mod<<endl;
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)
{
int now;
scanf("%lld",&now);
arr[i].A=Matrix_mul(Matrix_s(B,now,mod),A,mod);
//put(arr[i].A);
}
// for(int i=1;i<=n;i++)
// {
// cout<<arr[i].A.nmap[1][1]<<" ";
// }cout<<endl;
built(1,n,1,mod);
while(m--)
{
int cmd,l,r,v;
scanf("%lld%lld%lld",&cmd,&l,&r);
if(cmd==1)
{
scanf("%lld",&v);
Matrix C=Matrix_s(B,v,mod);
updata(1,n,1,l,r,C,mod);
}
else
{
printf("%lld\n",query(1,n,1,l,r,mod));
}
}
return 0;
}