您的位置:首页 > 其它

zoj 3772 线段树--单点更新

2014-04-06 22:39 393 查看
转自:点击打开链接

题意:

给一个序列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 1000000007

struct 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: