zoukankan      html  css  js  c++  java
  • CF718C Sasha and Array 线段树 + 矩阵乘法

    有两个操作:
    • 将 $[l,r]$所有数 + $x$
    • 求 $sum_{i=l}^{r}fib(i)$
    $n=m=10^5$  
    直接求不好求,改成矩阵乘法的形式: 
    $a_{i}=M^x imes fib_{1}$
    直接用线段树维护 $M^x$ 即可.
    因为矩阵乘法是满足结合律的: $A*B+A*C=A*(B+C)$
    #include <cstdio> 
    #include <algorithm>     
    #include <cstring> 
    #define lson (now << 1) 
    #define rson (now << 1 | 1)      
    #define ll long long   
    #define setIO(s) freopen(s".in", "r" , stdin) 
    using namespace std; 
    const int N = 200003; 
    const ll mod = 1000000007;      
    struct Matrix
    { 
        int n, m; 
        ll a[4][4];          
        ll * operator[] (int x)  { return a[x]; } 
        inline void re() 
        {
            for(int i = 0; i < 3 ; ++i) 
                for(int j = 0; j < 3; ++j) a[i][j] = 0;  
        }    
        inline void I() 
        {
            re(); 
            for(int i = 0; i < 3 ; ++i) a[i][i] = 1ll;     
        } 
        Matrix friend operator * (Matrix a, Matrix b) 
        { 
            Matrix c;   
            c.re();                           
            int i , j , k; 
            for(i = 0; i < a.n ; ++i) 
            {
                for(j = 0; j < b.m ; ++j) 
                    for(k = 0; k < a.m ; ++k) 
                    {
                        c[i][j] = (c[i][j] + (a[i][k] * b[k][j]) % mod) % mod;   
                    }  
            }
            c.n = a.n , c.m = b.m;     
            return c;       
        }         
        Matrix friend operator + (Matrix a, Matrix b) 
        {
            Matrix c; 
            c.n = 2, c.m = 1; 
            for(int i = 0; i < c.n ; ++i) 
            {
                for(int j = 0; j < c.m; ++j) c[i][j] = (a[i][j] + b[i][j]) % mod;    
            } 
            return c; 
        }
    }A[N], M, fib1, v;  
    Matrix operator ^ (Matrix a, int k) 
    {
        Matrix tmp; 
        tmp.n = tmp.m = 2;       
        for(tmp.I(); k ; a = a * a, k >>= 1) if(k & 1) tmp = tmp * a;    
        return tmp;    
    }                
    inline void init() 
    {
        M.re(), fib1.re(); 
        M.n = M.m = 2;    
        M[0][0] = 0, M[0][1] = 1, M[1][0] = 1, M[1][1] = 1;     
        fib1.n = 2, fib1.m = 1;  
        fib1[0][0] = 0, fib1[1][0] = 1;          
    }     
    int n , m ;  
    struct Node 
    { 
        Matrix sum, lazy; 
        int tag;     
    }t[N << 2];   
    inline void pushup(int l, int r, int now) 
    { 
        int mid = (l + r) >> 1; 
        t[now].sum = t[now << 1].sum;     
        if(r > mid) t[now].sum = t[now].sum + t[now << 1 | 1].sum;         
    }       
    inline void mark(int now, Matrix f) 
    {
        t[now].sum = f * t[now].sum ; 
        t[now].lazy = t[now].lazy * f;    
        t[now].tag = 1;           
    }  
    inline void pushdown(int l, int r, int now)
    {
        int mid = (l + r) >> 1;     
        if(t[now].tag) 
        { 
            mark(lson, t[now].lazy);   
            if(r > mid) mark(rson, t[now].lazy); 
            t[now].lazy.I(), t[now].tag = 0; 
        }
    }
    void build(int l, int r, int now) 
    { 
        t[now].lazy.n = t[now].lazy.m = 2;    
        t[now].lazy.I(); 
        t[now].tag = 0; 
        if(l == r) 
        {
            t[now].sum = A[l];       
            return ;  
        }
        int mid = (l + r) >> 1; 
        if(mid >= l) build(l, mid, lson); 
        if(r > mid) build(mid + 1, r, rson);    
        pushup(l, r, now);   
    } 
    void update(int l, int r, int now, int L, int R) 
    {
        if(l >= L && r <= R) 
        {
            mark(now , v);             
            return ; 
        } 
        pushdown(l, r, now); 
        int mid = (l + r) >> 1;    
        if(L <= mid) update(l, mid, lson, L, R); 
        if(R > mid) update(mid + 1, r, rson, L, R); 
        pushup(l, r, now);    
    } 
    ll query(int l, int r, int now, int L, int R) 
    {
        if(l >= L && r <= R)  return t[now].sum[1][0];    
        pushdown(l, r, now);   
        int mid = (l + r) >> 1;        
        ll g = 0;     
        if(L <= mid) g += query(l, mid, lson, L, R);   
        if(R  > mid) g += query(mid + 1, r, rson, L, R); 
        return (g % mod);     
    }
    int main() 
    { 
        // setIO("input");  
        init();       
        int i , j, x;              
        scanf("%d%d", &n, &m);           
        for(i = 1; i <= n ; ++i) 
        {
            scanf("%d", &x), A[i] = (M ^ (x - 1)) * fib1;                  
        }     
        build(1, n, 1);         
        for(int cas = 1, op , l, r, x; cas <= m ; ++cas) 
        {
            scanf("%d", &op); 
            if(op == 1) 
            {
                scanf("%d%d%d", &l, &r, &x);     
                if(x == 0) continue;       
                v = M ^ x;  
                update(1, n, 1, l, r); 
            } 
            if(op == 2) 
            {
                scanf("%d%d", &l, &r);    
                printf("%lld
    ", query(1, n, 1, l, r));     
            }
        }
        return 0; 
    }
    

      

  • 相关阅读:
    JS数组的相关方法
    JS字符串的相关方法
    重回我的园区
    STM32F405串口UART4波特率注意问题
    NXP MCU开始学习中
    锂电池测试
    FPGA与STM32并口通信
    NXP LPC4350绝对强悍,准备入手学习
    SDRAM+FPGA+MCU
    STM32+FPGA通信成功
  • 原文地址:https://www.cnblogs.com/guangheli/p/11350450.html
Copyright © 2011-2022 走看看