CF446C DZY Loves Fibonacci Numbers 题解
这个题解比我讲得好多了qaq 题解
线段树好题。
考虑我们对每个区间维护什么样的信息使其容易合并和Pushdown。
首先我们要加的斐波那契数列,很显然可以递推为前两项的值,即:
\(f_{i}=f_{i-1}+f_{i-2} \Rightarrow f_i=f_{i-1}\times f_2 \ + \ f_{i-2} \times f_1\)
那么对于一个确定的区间 \(l,r\),我们只需要维护后面一个式子中四项,就可以把要加的值和tag的修改值用前两项轻松地表示出来,便于合并和下传。事实上当 \(l,r\) 确定以后,\(f_{i-1}和f_{i-2}\) 也就等于 \(f_{r-l}\) 和 \(f_{r-l-1}\) ,只需要记录\(f_1,f_2\)。
记 \(sum\) 为 \(\sum_{i=1}^{r-l}f_i\),则一个区间维护的tag1实际上为:
\(sum \times \sum f_2\)。
tag2同理。
考虑 \(sum\) 可以前缀和,而且并不重要,我们只需每次累加 \(f_1\) 和 \(f_2\) 就行。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5+5;
const int mod=1e9+9;
int n,m,seq[MAXN];
long long f[MAXN];
struct Tree{
int l,r;
long long val,tag1,tag2;
}tree[MAXN<<2];
inline void Pre(){
f[1]=1,f[2]=1;
for(int i=3;i<=n+1;++i) f[i]=(f[i-1]+f[i-2])%mod;
}
inline void Build(int p,int l,int r){
tree[p].l=l,tree[p].r=r;
if(l==r){
tree[p].val=seq[l];
return;
}
int mid=(l+r)>>1;
Build(p<<1,l,mid);
Build(p<<1|1,mid+1,r);
tree[p].val=(tree[p<<1].val+tree[p<<1|1].val)%mod;
return;
}
inline void Pushdown(int p){
if(!tree[p].tag1&&!tree[p].tag2) return;
int mid=(tree[p].l+tree[p].r)>>1;
tree[p<<1].val=(tree[p<<1].val+tree[p].tag2*(f[mid-tree[p].l+2]-1)%mod+tree[p].tag1*f[mid-tree[p].l+1]%mod)%mod;
tree[p<<1].tag1=(tree[p<<1].tag1+tree[p].tag1)%mod,tree[p<<1].tag2=(tree[p<<1].tag2+tree[p].tag2)%mod;
int pos=mid-tree[p].l+2;
tree[p<<1|1].tag2=(tree[p<<1|1].tag2+f[pos]*tree[p].tag2%mod+f[pos-1]*tree[p].tag1%mod)%mod;
tree[p<<1|1].tag1=(tree[p<<1|1].tag1+f[pos-1]*tree[p].tag2%mod+f[pos-2]*tree[p].tag1%mod)%mod;
tree[p<<1|1].val=(tree[p<<1|1].val+tree[p].tag2*(f[tree[p].r-tree[p].l+2]-1)%mod+tree[p].tag1*f[tree[p].r-tree[p].l+1]%mod-tree[p].tag2*(f[mid-tree[p].l+2]-1)%mod-tree[p].tag1*f[mid-tree[p].l+1]%mod+mod)%mod;
tree[p].tag1=tree[p].tag2=0;
}
inline void Modify(int p,int l,int r){
if(tree[p].l>=l&&tree[p].r<=r){
tree[p].val=(tree[p].val+f[tree[p].r-tree[p].l+1]*f[tree[p].l-l+1]%mod+(f[tree[p].r-tree[p].l+2]-1)*f[tree[p].l-l+2]%mod)%mod;
tree[p].tag1+=f[tree[p].l-l+1],tree[p].tag2+=f[tree[p].l-l+2],tree[p].tag1%=mod,tree[p].tag2%=mod;
return;
}
Pushdown(p);
int mid=(tree[p].l+tree[p].r)>>1;
if(l<=mid) Modify(p<<1,l,r);
if(mid<r) Modify(p<<1|1,l,r);
tree[p].val=(tree[p<<1].val+tree[p<<1|1].val)%mod;
return;
}
inline long long Query(int p,int l,int r){
if(tree[p].l>=l&&tree[p].r<=r) return tree[p].val;
Pushdown(p);
int mid=(tree[p].l+tree[p].r)>>1;
long long ans=0;
if(l<=mid) ans=Query(p<<1,l,r);
if(mid<r) ans+=Query(p<<1|1,l,r);
return ans%mod;
}
int main(){
int id,x,y;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",&seq[i]);
Pre(),Build(1,1,n);
for(int i=1;i<=m;++i){
scanf("%d %d %d",&id,&x,&y);
if(id&1) Modify(1,x,y);
else printf("%d\n",(Query(1,x,y)+mod)%mod);
}
return 0;
}

浙公网安备 33010602011771号