题目链接:
把\(A,B,C\)组成矩阵\([A,B,C]\),那么每一次操作就可以用矩阵表示:
- \(A=A+B\)
\(\times \begin{bmatrix}1&0&0\\1&1&0\\0&0&1\end{bmatrix}\)
\(B=B+C,C=C+A\)类似。
- \(A=A+v\)
\(+[v,0,0]\)
- \(B=B*v\)
\(\times \begin{bmatrix}1&0&0\\0&v&0\\0&0&1\end{bmatrix}\)
- \(C=v\)
\(\times \begin{bmatrix}1&0&0\\1&0&0\\0&0&0\end{bmatrix}\)
\(+[0,0,v]\)
然后线段树区间操作即可,注意优先级。
每一次乘法标记清空时要置为单位矩阵。
时间复杂度 \(O(27n\log n)\)
代码(常数爆炸):
#include#include #include #define rint register inttypedef long long ll;#define Getchar (p1==p2&&(p2=(p1=In)+fread(In,1,1<<21,stdin),p1==p2)?EOF:*p1++)char In[1<<21],*p1=In,*p2=In,Ch,Out[8000005],*Outp=Out,St[15],*Tp=St;inline int Getint(rint x=0){ while(!isdigit(Ch=Getchar)); for(;isdigit(Ch);Ch=Getchar)x=x*10+(Ch^48); return x;}inline void Putint(int x,const char c){ do *Tp++=x%10^48;while(x/=10); do *Outp++=*--Tp;while(Tp!=St); *Outp++=c;}const int Mod=998244353;inline int Add(int a,int b){return (a+=b)>=Mod?a-Mod:a;}struct Matrix{ int n,m,a[3][3]; inline void Clear(){memset(a,0,sizeof a);} inline Matrix(const int ns=0,const int ms=0){n=ns,m=ms,Clear();} inline void Init(const int ns,const int ms){n=ns,m=ms;} inline void IOne(){for(rint i=0;i >1)void Build(int p,int l,int r){ Sum[p].Init(1,3),TMul[p].Init(3,3),TAdd[p].Init(1,3),TMul[p].IOne(); if(l==r){for(rint i=0;i<3;++i)Sum[p].a[0][i]=Getint();return;} Build(Lc,l,Mid),Build(Rc,Mid+1,r),Sum[p]=Sum[Lc]+Sum[Rc];}inline void Pushdown(int p,int l,int r){ TMul[Lc]=TMul[Lc]*TMul[p]; TMul[Rc]=TMul[Rc]*TMul[p]; TAdd[Lc]=TAdd[Lc]*TMul[p]+TAdd[p]; TAdd[Rc]=TAdd[Rc]*TMul[p]+TAdd[p]; Sum[Lc]=Sum[Lc]*TMul[p]+TAdd[p]*(Mid-l+1); Sum[Rc]=Sum[Rc]*TMul[p]+TAdd[p]*(r-Mid); TMul[p].Clear(),TAdd[p].Clear(),TMul[p].IOne();}inline void Modify(int p,int l,int r,int tl,int tr,const Matrix &o,int t)//t=0 Mul t=1 Add{ if(tl<=l&&r<=tr) { if(!t)TMul[p]=TMul[p]*o,TAdd[p]=TAdd[p]*o,Sum[p]=Sum[p]*o; else TAdd[p]=TAdd[p]+o,Sum[p]=Sum[p]+o*(r-l+1); return; } Pushdown(p,l,r); if(tl<=Mid)Modify(Lc,l,Mid,tl,tr,o,t); if(tr>Mid)Modify(Rc,Mid+1,r,tl,tr,o,t); Sum[p]=Sum[Lc]+Sum[Rc];}inline Matrix Query(int p,int l,int r,int tl,int tr){ if(tl<=l&&r<=tr)return Sum[p]; Pushdown(p,l,r); Matrix Res(1,3); if(tl<=Mid)Res=Query(Lc,l,Mid,tl,tr); if(tr>Mid)Res=Res+Query(Rc,Mid+1,r,tl,tr); return Res;}int main(){ freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); Build(1,1,n=Getint()),m=Getint(); Matrix M1(3,3),M2(3,3),M3(3,3),A4(1,3),M5(3,3),M6(3,3),A6(1,3),Res; M1.a[0][0]=1,M1.a[1][0]=1,M1.a[1][1]=1,M1.a[2][2]=1; M2.a[0][0]=1,M2.a[1][1]=1,M2.a[2][1]=1,M2.a[2][2]=1; M3.a[0][0]=1,M3.a[0][2]=1,M3.a[1][1]=1,M3.a[2][2]=1; M5.a[0][0]=1,M5.a[2][2]=1,M6.a[0][0]=1,M6.a[1][1]=1; for(rint op,l,r;m--;) { op=Getint(),l=Getint(),r=Getint(); if(op==1)Modify(1,1,n,l,r,M1,0); else if(op==2)Modify(1,1,n,l,r,M2,0); else if(op==3)Modify(1,1,n,l,r,M3,0); else if(op==4)A4.a[0][0]=Getint(),Modify(1,1,n,l,r,A4,1); else if(op==5)M5.a[1][1]=Getint(),Modify(1,1,n,l,r,M5,0); else if(op==6)A6.a[0][2]=Getint(),Modify(1,1,n,l,r,M6,0),Modify(1,1,n,l,r,A6,1); else Res=Query(1,1,n,l,r),Putint(Res.a[0][0],' '),Putint(Res.a[0][1],' '),Putint(Res.a[0][2],'\n'); } return fwrite(Out,1,Outp-Out,stdout),0;}