Water Sequence Problem By liuzhangfeiabc - 线段树 - 矩阵乘法

题目大意:给你两个序列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<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#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<<"="<<x
#define sp <<" "
#define ln <<endl
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<<v[i][j]<<" ";
        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(mid<t) update(rt->ch[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(mid<t) (ans+=query(rt->ch[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;
}

猜你喜欢

转载自blog.csdn.net/mys_c_k/article/details/80429262