zoj 3772 线段树--单点更新

来源:互联网 发布:js call apply 区别 编辑:程序博客网 时间:2024/05/22 13:33

转自:点击打开链接

题意:

给一个序列An

有m个询问,每个询问包括l和r

定义f(l) = a[l], f(l+1) = a[l+1], f(x)=f(x-1) + a[x] * f(x-2), x >= l + 2;

对每个询问,求f(r);


当x>=l+2时,

f(x)=f(x-1) + a[x]* f(x-2), 所以就有递推式


所以当r>=l+1时,


然后就可以先求出:


用线段树就可以在O(logn)的时间求出这个式子,不过线段树的每个节点保存的是一个矩阵

还有就是要注意矩阵乘的方向

总的复杂度是O(nlogn+mlogn)

WA注意用long long

AC代码如下:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define MOD 1000000007struct Matrix{    long long num[2][2];    Matrix( int n ){        num[0][0] = 1;        num[0][1] = n;        num[1][0] = 1;        num[1][1] = 0;    }    Matrix(){        memset( num, 0, sizeof( num ) );    }    Matrix operator*( const Matrix &b ) const{        Matrix mm;        for( int i = 0; i < 2; i++ ){            for( int j = 0; j < 2; j++ ){                mm.num[i][j] = 0;                for( int k = 0; k < 2; k++ ){                    mm.num[i][j] = ( mm.num[i][j] +  ( num[i][k] % MOD ) * ( b.num[k][j] % MOD ) ) % MOD;                }            }        }        return mm;    }};Matrix m[400000];long long num[110000];int N, M;int lc( int root ){    return 2 * root;}int rc( int root ){    return 2 * root + 1;}void updata( int root ){    m[root] = m[rc(root)] * m[lc(root)];}void built( int l, int r, int root ){    if( l == r ){        long long temp;        scanf( "%lld", &temp );        Matrix tt( temp );        m[root] = tt;        num[l] = temp;        return;    }    int mid = ( l + r ) / 2;    built( l, mid, lc( root ) );    built( mid + 1, r, rc( root ) );    updata( root );}Matrix query( int L, int R, int l, int r, int root ){    if( L <= l && R >= r ){        return m[root];    }    Matrix a, b;    int mid = ( l + r ) / 2;    if( L <= mid )  a = query( L, R, l, mid, lc( root ) );    if( R > mid )   b = query( L, R, mid + 1, r, rc( root ) );    if( L > mid )  return b;    if( R <= mid ) return a;    return b * a;}int main(){    int T;    cin >> T;    while( T-- ){        cin >> N >> M;        built( 1, N, 1 );        for( int i = 1; i <= M; i++ ){            int l, r;            scanf( "%d%d", &l, &r );            if( r - l <= 1 ){                cout << num[r] << endl;            }else{                Matrix mm = query( l + 2, r, 1, N, 1 );                cout << ( num[l] % MOD * mm.num[0][1] % MOD + num[l+1] % MOD * mm.num[0][0] % MOD ) % MOD << endl;;            }        }    }    return 0;}


0 0
原创粉丝点击