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\n",query(1,n,1,l,r,mod));
        }
    }
    return 0;
}

 

posted @ 2019-02-20 14:39  Minun  阅读(86)  评论(0编辑  收藏  举报