[LOJ2980]「THUSCH 2017」大魔法师

题目链接:

#2980. 「THUSCH 2017」大魔法师

\(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 <cstdio>
#include <cctype>
#include <cstring>
#define rint register int
typedef 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<n;++i)a[i][i]=1;}

    inline Matrix operator+(const Matrix &o)const
    {
        Matrix Res(n,m);
        for(rint i=0;i<n;++i)
            for(rint j=0;j<m;++j)
                Res.a[i][j]=Add(a[i][j],o.a[i][j]);
        return Res;
    }

    inline Matrix operator*(const int k)const
    {
        Matrix Res(n,m);
        for(rint i=0;i<n;++i)
            for(rint j=0;j<m;++j)
                Res.a[i][j]=(ll)a[i][j]*k%Mod;
        return Res;
    }

    inline Matrix operator*(const Matrix &o)const
    {
        Matrix Res(n,o.m);
        for(rint i=0;i<n;++i)
            for(rint k=0;k<m;++k)
                for(rint j=0;j<o.m;++j)
                    Res.a[i][j]=Add(Res.a[i][j],(ll)a[i][k]*o.a[k][j]%Mod);
        return Res;
    }
};

int n,m;
Matrix Sum[1000005],TMul[1000005],TAdd[1000005];
#define Lc (p<<1)
#define Rc (p<<1|1)
#define Mid ((l+r)>>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;
}
posted @ 2019-09-07 20:43  LanrTabe  阅读(523)  评论(0编辑  收藏  举报