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;
}

sto Orz liulianLL!

posted @ 2024-09-24 20:45  mountzhu  阅读(17)  评论(0)    收藏  举报