トピック要件はターンJiafeiボーフィボナッチ数列の数、間隔合計で間隔をサポートするデータ構造を維持します。
最初に私には、フィボナッチ列のプレフィックスや数式、その後、次のパスを使用して、同様の等差数列を維持することを考えて、私はすぐにこの考え方に問題があることを発見しました。
しかし、この考え方は、数フィボナッチ数列であることを我々はフィボナッチ一般的な用語の式を見て、実際に有用である:
\(F_n = \ FRAC {1} {\ SQRT {5}} [(\ FRAC {1 + \ SQRT {5}} {2 })^ N - (\ FRAC {1 - \ SQRT {5}} {2})^ N] \)
実際には、フィボナッチ列は、二つの幾何学的な配列との間の差として見ることができます。私たちは尋ねるかもしれませんので、この問題は、剰余が必要です\(\ sqrtの{5} \ ) 金型に\(10 ^ 9 + 9 \)をすることによって感覚を法問題への解決策をコピーしますどの383008016の係数を計算することができ、かつ2等比級数快適性を維持することができます。
メンテナンスだけで合格する最初の項目の下に、いくつか明らかに一般的な比率は比較的簡単です。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<vector>
#include<set>
#include<map>
#include<string>
#include<iostream>
#include<queue>
#include<cctype>
using namespace std;
#define A(x) cout << #x << " " << x << endl;
#define AA(x,y) cout << #x << " " << x << #y << " " << y << endl;
#define B cout << "Break" << endl;
#define ll long long
#define inf 1000000000
ll read()
{
ll c = getchar();
int x = 0,f = 1;
while(!isdigit(c))
{
if(c == '-') f = -1;
c = getchar();
}
while(isdigit(c))
{
x = x * 10 + c - '0';
c = getchar();
}
return f * x;
}
#define N 300010
#define mod 1000000009
ll base1,base2,inv,n,m;
int seq[N];
ll quick_pow(ll a,ll b)
{
ll ret = 1;
while(b)
{
if(b & 1) ret = ret * a % mod;
a = a * a % mod;
b >>= 1;
}
return ret % mod;
}
struct Segment_Tree
{
#define mid (l + r >> 1)
#define ls x << 1,l,mid
#define rs x << 1 | 1,mid + 1,r
ll p[N],tree[N << 2],lazy[N << 2],q,Inv;
void init()
{
p[0] = 1;
for(ll i = 1;i <= n;++i) p[i] = p[i - 1] * q % mod;
Inv = quick_pow(q - 1,mod - 2);
build(1,1,n);
return;
}
void push_up(ll x)
{
tree[x] = (tree[x << 1] + tree[x << 1 | 1]) % mod;
return;
}
void build(ll x,ll l,ll r)
{
if(l == r) return;
build(ls);
build(rs);
push_up(x);
return;
}
void add(ll x,ll l,ll r,ll a)
{
lazy[x] += a;
tree[x] += (a * p[r - l + 1] % mod - a + mod) % mod * Inv % mod;
return;
}
void push_down(ll x,ll l,ll r)
{
if(!lazy[x]) return;
add(ls,lazy[x]);
add(rs,lazy[x] * p[r - l + 1] % mod);
lazy[x] = 0;
}
void modify(ll x,ll l,ll r,ll L,ll R,ll a)
{
if(l == L && r == R)
{
add(x,l,r,a);
return;
}
push_down(x,l,r);
if(r <= mid) modify(ls,L,R,a);
else if(l > mid) modify(rs,L,R,a);
else
{
modify(ls,L,mid,a);
modify(rs,mid + 1,R,a * p[mid - L + 1] % mod);
}
push_up(x);
return;
}
ll query(ll x,ll l,ll r,ll L,ll R)
{
if(l == L && r == R) return tree[x];
push_down(x,l,r);
if(r <= mid) return query(ls,L,R);
else if(l > mid) return query(rs,L,R);
else return (query(ls,L,mid) + query(rs,mid + 1,R)) % mod;
}
}t1,t2;
int main()
{
t1.q = (383008016 + 1) * quick_pow(2ll,mod - 2) % mod;
t2.q = (1 - 383008016 + mod) * quick_pow(2ll,mod - 2) % mod;
inv = quick_pow(383008016,mod - 2);
n = read(),m = read();
for(ll i = 1;i <= n;++i) seq[i] = (seq[i - 1] + read()) % mod;
t1.init(),t2.init();
while(m--)
{
ll op = read(),l = read(),r = read();
if(op == 1)
{
t1.modify(1,1,n,l,r,t1.q);
t2.modify(1,1,n,l,r,t2.q);
}
else
{
ll a = t1.query(1,1,n,l,r);
ll b = t2.query(1,1,n,l,r);
ll ans = (a - b + mod) % mod * inv % mod;
printf("%lld\n",((seq[r] - seq[l - 1] + mod) % mod + ans) % mod);
}
}
}