zoukankan      html  css  js  c++  java
  • CodeForces 718C Sasha and Array

    线段树。

    线段树维护区间矩阵和,操作都是最简单的线段树。$lazy$标记不要记录乘了几次,直接记录乘了几次之后的矩阵就可以了,不然每次下传的时候再算一遍时间复杂度会提高。

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    #include<stack>
    #include<bitset>
    #include<iostream>
    using namespace std;
    typedef long long LL;
    const double pi=acos(-1.0),eps=1e-6;
    void File()
    {
        freopen("D:\in.txt","r",stdin);
        freopen("D:\out.txt","w",stdout);
    }
    template <class T>
    inline void read(T &x)
    {
        char c=getchar(); x=0;
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) {x=x*10+c-'0'; c=getchar();}
    }
    
    int mod=1e9+7;
    const int maxn=100010;
    struct Matrix
    {
        int A[3][3]; int R,C;
    }s[4*maxn],t[4*maxn];
    int n,m;
    Matrix Q,Z,P;
    
    Matrix ch(Matrix a,Matrix b)
    {
        Matrix c;
        int i, j, k;
        for (i = 1; i <= a.R; i++)
            for (j = 1; j <= b.C; j++){
                c.A[i][j]=0;
                for (k = 1; k <= a.C; k++){
                    LL aa=(LL)a.A[i][k],bb=(LL)b.A[k][j];
                    LL cc=aa*bb%(LL)mod;
                    int dd=(int)cc;
                    c.A[i][j] = (c.A[i][j] + dd)%mod;
                }
            }
        c.R=a.R; c.C=b.C;
        return c;
    }
    
    Matrix pow(LL p)
    {
        Matrix X,Y;
    
        X.R=2; X.C=2; Y.R=2; Y.C=2;
    
        Y.A[1][1]=1; Y.A[1][2]=0;
        Y.A[2][1]=0; Y.A[2][2]=1;
    
        X.A[1][1]=0; X.A[1][2]=1;
        X.A[2][1]=1; X.A[2][2]=1;
    
        while (p)
        {
            if (p % 2 == 1) Y = ch(Y,X);
            p = p >> 1;
            X = ch(X,X);
        }
        return Y;
    }
    
    void pushUp(int rt)
    {
        s[rt].R=2; s[rt].C=2;
        s[rt].A[1][1]=(s[2*rt].A[1][1]+s[2*rt+1].A[1][1])%mod;
        s[rt].A[1][2]=(s[2*rt].A[1][2]+s[2*rt+1].A[1][2])%mod;
        s[rt].A[2][1]=(s[2*rt].A[2][1]+s[2*rt+1].A[2][1])%mod;
        s[rt].A[2][2]=(s[2*rt].A[2][2]+s[2*rt+1].A[2][2])%mod;
    }
    
    bool check(Matrix x)
    {
        if(x.A[1][1]!=1) return 0;
        if(x.A[1][2]!=0) return 0;
        if(x.A[2][1]!=0) return 0;
        if(x.A[2][2]!=1) return 0;
        return 1;
    }
    
    void pushDown(int rt)
    {
        if(check(t[rt])==1) return;
    
        s[2*rt]=ch(s[2*rt],t[rt]); t[2*rt]=ch(t[2*rt],t[rt]);
        s[2*rt+1]=ch(s[2*rt+1],t[rt]); t[2*rt+1]=ch(t[2*rt+1],t[rt]);
    
        t[rt].A[1][1]=1; t[rt].A[1][2]=0;
        t[rt].A[2][1]=0; t[rt].A[2][2]=1;
    }
    
    void build(int l,int r,int rt)
    {
        t[rt].A[1][1]=1; t[rt].A[1][2]=0;
        t[rt].A[2][1]=0; t[rt].A[2][2]=1;
        t[rt].R=2; t[rt].C=2;
    
        if(l==r)
        {
            LL x; scanf("%lld",&x);
    
            s[rt].R=2; s[rt].C=2;
            s[rt].A[1][1]=1; s[rt].A[1][2]=0;
            s[rt].A[2][1]=0; s[rt].A[2][2]=1;
    
            s[rt]=ch(s[rt],pow(x-1));
            return;
        }
    
        int m=(l+r)/2;
        build(l,m,2*rt);
        build(m+1,r,2*rt+1);
        pushUp(rt);
    }
    
    void update(int L,int R,LL x,int l,int r,int rt)
    {
        if(L<=l&&r<=R)
        {
            s[rt]=ch(s[rt],P);
            t[rt]=ch(t[rt],P);
            return ;
        }
    
        int m=(l+r)/2;
        pushDown(rt);
        if(L<=m) update(L,R,x,l,m,2*rt);
        if(R>m) update(L,R,x,m+1,r,2*rt+1);
        pushUp(rt);
    }
    
    void add(Matrix a)
    {
        Q.A[1][1]=(Q.A[1][1]+a.A[1][1])%mod;
        Q.A[1][2]=(Q.A[1][2]+a.A[1][2])%mod;
        Q.A[2][1]=(Q.A[2][1]+a.A[2][1])%mod;
        Q.A[2][2]=(Q.A[2][2]+a.A[2][2])%mod;
    }
    
    void get(int L,int R,int l,int r,int rt)
    {
        if(L<=l&&r<=R) { add(s[rt]); return ; }
    
        int m=(l+r)/2;
        pushDown(rt);
        if(L<=m) get(L,R,l,m,2*rt);
        if(R>m) get(L,R,m+1,r,2*rt+1);
        pushUp(rt);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        build(1,n,1);
        for(int i=1;i<=m;i++)
        {
            int op; scanf("%d",&op);
            int L,R; scanf("%d%d",&L,&R);
            if(op==1)
            {
                LL x; scanf("%lld",&x);
                P=pow(x); update(L,R,x,1,n,1);
            }
            else
            {
                Q.R=2; Q.C=2; memset(Q.A,0,sizeof Q.A);
                get(L,R,1,n,1);
                Z.R=1; Z.C=2; Z.A[1][1]=1; Z.A[1][2]=1;
                Z=ch(Z,Q);
                printf("%d
    ",Z.A[1][1]);
            }
        }
        return 0;
    }
  • 相关阅读:
    请问发表的文章如何备份?
    .NET中利用XML来自动生成代码策略
    XPO使用随笔
    为方便做封包分析,做了个十六进制和字符互转的网页小工具
    前端人员如何模拟慢网速环境
    补充《动态加载外部.js文件时候,javascript的执行顺序问题》
    凡客诚品官方网站的前端改进建议
    "Cachecontrol”常见的取值private、nocache、maxage、mustrevalidate及其用意
    javascript跨域操作cookie的点滴记录
    HTTPS的七个误解(译文转载)
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5922310.html
Copyright © 2011-2022 走看看