题目大意:给你两个序列A和B,维护A/B的区间加,区间A=B和A+=B和B=A和B+=A,以及求区间和
题解:发现这是个线性变换,用线段树维护矩阵即可,略卡常;
// luogu-judger-enable-o2
// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include
#include
#include
#include
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define lint long long
#define mod 1000000007
#define N 100010
#define gc getchar()
#define debug(x) cerr<<#x<<"="<
#define sp <<" "
#define ln <
using namespace std;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
int a[N],b[N];lint w[5][5];
struct matrix{
int v[5][5],n,m;
matrix(int _n=0,int _m=0)
{
n=_n,m=_m;
rep(i,1,n) memset(v[i],0,sizeof(int)*(m+1));
}
inline matrix& operator=(const matrix &b)
{
n=b.n,m=b.m;
rep(i,1,n) memcpy(v[i],b.v[i],sizeof(int)*(m+1));
return *this;
}
inline matrix operator+(const matrix &b)
{
matrix c(n,m);
rep(i,1,n) rep(j,1,m)
c.v[i][j]=v[i][j]+b.v[i][j],(c.v[i][j]>=mod?c.v[i][j]-=mod:0);
return c;
}
inline matrix operator*(const matrix &b)const
{
matrix a=*this,c(n,b.m);
rep(i,1,n) rep(k,1,m) rep(j,1,b.m)
w[i][j]+=(lint)a.v[i][k]*b.v[k][j];
rep(i,1,n) rep(j,1,b.m) c.v[i][j]=w[i][j]%mod,w[i][j]=0ll;
return c;
}
inline matrix& operator*=(const matrix &b)
{ return (*this)=(*this)*b; }
inline bool operator!=(const matrix &b)const
{
if(n!=b.n||m!=b.m) return true;
rep(i,1,n) rep(j,1,m)
if(v[i][j]^b.v[i][j]) return true;
return false;
}
inline int show()
{
debug(n)sp,debug(m)ln;
for(int i=1;i<=n;i++,cerr ln)
rep(j,1,m) cerr<" " ;
return cerr ln,0;
}
}Imtx,mtx[10],res;
inline matrix pm(int x,int p) { return res=Imtx,res.v[p][3]=x,res; }
struct segment{
int l,r;matrix pt,v;
segment *ch[2];
}*rt;
inline int push_up(segment* &rt)
{
return rt->v=rt->ch[0]->v+rt->ch[1]->v,0;
}
inline int update_tags(segment* &rt,const matrix &b)
{
return rt->pt=b*rt->pt,rt->v=b*rt->v,0;
}
inline int push_down(segment* &rt)
{
update_tags(rt->ch[0],rt->pt),
update_tags(rt->ch[1],rt->pt);
return rt->pt=Imtx,0;
}
int build(segment* &rt,int l,int r)
{
rt=new segment,rt->pt=rt->v=Imtx,rt->l=l,rt->r=r,rt->v.n=3,rt->v.m=1;
int mid=(l+r)>>1;
if(l==r) return rt->v.v[1][1]=a[l],rt->v.v[2][1]=b[r],rt->v.v[3][1]=1;
return build(rt->ch[0],l,mid),build(rt->ch[1],mid+1,r),push_up(rt),0;
}
int update(segment* &rt,int s,int t,const matrix &b)
{
int l=rt->l,r=rt->r,mid=(l+r)>>1;
if(s<=l&&r<=t) return update_tags(rt,b);
if(rt->pt!=Imtx) push_down(rt);
if(s<=mid) update(rt->ch[0],s,t,b);
if(midch[1],s,t,b);
return push_up(rt);
}
int query(segment* &rt,int s,int t,int k)
{
int l=rt->l,r=rt->r,mid=(l+r)>>1;
if(s<=l&&r<=t) return rt->v.v[k][1];
int ans=0;if(rt->pt!=Imtx) push_down(rt);
if(s<=mid) (ans+=query(rt->ch[0],s,t,k))%=mod;
if(midch[1],s,t,k))%=mod;
return ans;
}
char ss[2000000],tt[20];int ssl,ttl;
inline int show(int x)
{
if(!x) return ss[++ssl]='0';
ttl=0;while(x) tt[++ttl]=x%10+'0',x/=10;
while(ttl--) ss[++ssl]=tt[ttl+1];ss[++ssl]='\n';
return 0;
}
int main()
{
// freopen("data.in","r",stdin);
// freopen("std.out","w",stdout);
int n=inn(),q=inn(),opt,s,t;
rep(i,1,n) a[i]=inn();rep(i,1,n) b[i]=inn();
Imtx.n=Imtx.m=3;rep(i,1,3) Imtx.v[i][i]=1;
rep(i,3,6) mtx[i].n=mtx[i].m=3;
mtx[3].v[1][2]=mtx[3].v[2][2]=mtx[3].v[3][3]=1;
mtx[4].v[1][1]=mtx[4].v[2][1]=mtx[4].v[3][3]=1;
mtx[5].v[1][1]=mtx[5].v[1][2]=mtx[5].v[2][2]=mtx[5].v[3][3]=1;
mtx[6].v[1][1]=mtx[6].v[2][1]=mtx[6].v[2][2]=mtx[6].v[3][3]=1;
build(rt,1,n);
while(q--)
if((opt=inn())<=2) s=inn(),t=inn(),update(rt,s,t,pm(inn(),opt));
else if(opt<=6) s=inn(),t=inn(),update(rt,s,t,mtx[opt]);
else s=inn(),t=inn(),show(query(rt,s,t,((opt&1)^1)+1));
return fwrite(ss+1,sizeof(char),ssl,stdout),0;
}