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
- zoj 3772 线段树--单点更新
- zoj (单点更新区间查询:线段树)
- zoj 3279 Ants (线段树单点更新)
- zoj 3633 线段树单点更新 区间最大值
- zoj 3635 线段树 区间求位置 单点更新
- ZOJ 3279 Ants(线段树单点更新和查询)
- zoj 3279 ants 线段树+单点更新+查询下标
- 线段树 单点更新
- 线段树单点更新
- 线段树 单点更新
- 单点更新线段树
- 线段树单点更新
- 线段树单点更新
- 线段树 单点更新
- 线段树 单点更新
- 线段树单点更新
- 线段树 单点更新
- 单点更新线段树
- 和法国恢复
- DIB函数注释
- 屏幕坐标转换分析
- 第一次写博客
- ActiveMQ集群:网络连接模式(network connector)详解
- zoj 3772 线段树--单点更新
- VS2010 快捷键大全
- openjdk
- Android UI控件详解-Spinner(下拉列表)
- 安装ubuntu之后的一些设置总结(更新ing)
- 在Ubuntu 12.04安装和设置SSH服务
- [贰]Pomelo游戏服务器编程分享 之 环境搭建
- 未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序。
- AOE网络与关键路径(一)