• Codeforces Round 718C Sasha and Array (矩阵线段树)


    题解思路:

    线段树维护,

    用矩阵求斐波那契值,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
    ",query(1,n,1,l,r,mod));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    关于IIS7发布网站
    二叉树遍历逆向
    山药熬粥补脾
    山萸肉补肝阴
    生黄芪痔疮
    酸石榴
    生石膏粉清实热
    熟地黄被肾阴
    龙眼肉(桂圆肉)
    鸡内金消食导滞
  • 原文地址:https://www.cnblogs.com/minun/p/10473759.html
Copyright © 2020-2023  润新知