題目大意:
兩種操作,區間加上一個斐波那契數列,區間求和。
思路:
考慮用線段樹來實現區間加法,但是加上的是一個斐波那契數列,所以加法的標記爲一段斐波那契數列。
顯然錯開的斐波那契數列可能加到線段樹的同一個結點,似乎不好合並這個區間擁有的兩段斐波那契數列的標記。於是考慮斐波那契數列本身的性質,它是形爲 這樣的序列,我們在一個區間上面維護了兩段這樣的序列,不難發現這兩段滿足上述遞推的序列在合併了之後還是滿足上述遞推序列,所以我們只需要變換這個區間的前兩項即可。
至於區間的和與前兩項的關係以及區間中的任意一項與前兩項的關係可以預處理出係數,這樣就可以在線段樹上實現查詢和pushdown了。
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
typedef long long ll;
using namespace std;
void File(){
freopen("CF446C.in","r",stdin);
freopen("CF446C.out","w",stdout);
}
template<typename T>void read(T &_){
T __=0,mul=1; char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')mul=-1;
ch=getchar();
}
while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar();
_=__*mul;
}
const int maxn=3e5+10;
const ll mod=1e9+9;
int n,m;
ll f[maxn],cnt1[maxn],cnt2[maxn],sum1[maxn],sum2[maxn];
void add(ll &_,ll __){_=_+__;if(_>mod)_%=mod;}
struct Segment_Tree{
#define mid ((l+r)>>1)
#define lc rt<<1
#define rc rt<<1|1
#define lson lc,l,mid
#define rson rc,mid+1,r
ll f1[maxn<<2],f2[maxn<<2],sum[maxn<<2];
void build(int rt,int l,int r){
if(l==r)read(sum[rt]);
else{
build(lson),build(rson);
sum[rt]=(sum[lc]+sum[rc])%mod;
}
}
void pushdown(int rt,int l,int r){
if(l+1==r)add(sum[lc],f1[rt]),add(sum[rc],f2[rt]);
else{
add(f1[lc],f1[rt]); add(f2[lc],f2[rt]);
ll ff1=(f1[rt]*cnt1[mid+2-l]+f2[rt]*cnt2[mid+2-l])%mod;
ll ff2=(f1[rt]*cnt1[mid+3-l]+f2[rt]*cnt2[mid+3-l])%mod;
add(f1[rc],ff1); add(f2[rc],ff2);
add(sum[lc],(f1[rt]*sum1[mid-l+1]+f2[rt]*sum2[mid-l+1])%mod);
add(sum[rc],(ff1*sum1[r-mid]+ff2*sum2[r-mid])%mod);
}
f1[rt]=f2[rt]=0;
}
void update(int rt,int l,int r,int L,int R){
if(L<=l && r<=R){
if(l==r)add(sum[rt],f[l-L+1]);
else{
add(sum[rt],(f[l-L+1]*sum1[r-l+1]+f[l-L+2]*sum2[r-l+1]));
add(f1[rt],f[l-L+1]); add(f2[rt],f[l-L+2]);
}
}
else{
if(f1[rt] || f2[rt])pushdown(rt,l,r);
if(L<=mid)update(lson,L,R);
if(R>=mid+1)update(rson,L,R);
sum[rt]=(sum[lc]+sum[rc])%mod;
}
}
ll query(int rt,int l,int r,int L,int R){
if(L<=l && r<=R)return sum[rt];
if(f1[rt] || f2[rt])pushdown(rt,l,r);
ll ret=0;
if(L<=mid)ret=(ret+query(lson,L,R))%mod;
if(R>=mid+1)ret=(ret+query(rson,L,R))%mod;
return ret;
}
}T;
void init(){
read(n); read(m);
f[1]=f[2]=1;
REP(i,3,n)f[i]=(f[i-1]+f[i-2])%mod;
T.build(1,1,n);
cnt1[1]=cnt2[2]=1;
sum1[1]=sum1[2]=sum2[2]=1;
REP(i,3,n){
cnt1[i]=(cnt1[i-1]+cnt1[i-2])%mod;
cnt2[i]=(cnt2[i-1]+cnt2[i-2])%mod;
sum1[i]=(sum1[i-1]+cnt1[i])%mod;
sum2[i]=(sum2[i-1]+cnt2[i])%mod;
}
}
void work(){
int ty,x,y;
REP(i,1,m){
read(ty); read(x); read(y);
// REP(j,1,n)printf("%lld ",T.query(1,1,n,j,j));
// putchar('\n');
if(ty==1)T.update(1,1,n,x,y);
else printf("%lld\n",T.query(1,1,n,x,y));
}
}
int main(){
File();
init();
work();
return 0;
}