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;
    }
  • 相关阅读:
    【POJ 3162】 Walking Race (树形DP-求树上最长路径问题,+单调队列)
    【POJ 2152】 Fire (树形DP)
    【POJ 1741】 Tree (树的点分治)
    【POJ 2486】 Apple Tree (树形DP)
    【HDU 3810】 Magina (01背包,优先队列优化,并查集)
    【SGU 390】Tickets (数位DP)
    【SPOJ 2319】 BIGSEQ
    【SPOJ 1182】 SORTBIT
    【HDU 5456】 Matches Puzzle Game (数位DP)
    【HDU 3652】 B-number (数位DP)
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5922310.html
Copyright © 2011-2022 走看看