社区讨论
玄关求条(或者hack),经典斐波那契线段树题,
CF446CDZY Loves Fibonacci Numbers参与者 1已保存回复 1
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @lzz112mj
- 此快照首次捕获于
- 2024/08/18 11:47 2 年前
- 此快照最后确认于
- 2024/08/18 14:35 2 年前
采用的是维护每个区块前两项的做法
CPP#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=3e5+10,mod=1e9+7;
ll fbi[N],sfbi[N];
int n,m;
ll a[N];
struct node{
int l,r;
ll tag1,tag2;
ll sum;
}rt[4*N];
void build(int l,int r,int k){
rt[k].l=l,rt[k].r=r,rt[k].tag1=rt[k].tag2=0;
if(l==r){rt[k].sum=a[l];rt[k].sum%=mod;return;}
int mid=(l+r)>>1;
build(l,mid,k<<1),build(mid+1,r,k<<1|1);
rt[k].sum=rt[k<<1].sum+rt[k<<1|1].sum;
rt[k].sum%=mod;
}
void upsum(int k){
rt[k].sum=(rt[k<<1].sum+rt[k<<1|1].sum)%mod;
}
void down(int k){
rt[k<<1].tag1+=rt[k].tag1;
rt[k<<1].tag2+=rt[k].tag2;
int len=rt[k<<1].r-rt[k<<1].l+1;
rt[k<<1].sum+=(rt[k].tag1*fbi[len]+rt[k].tag2*fbi[len+1]+mod-rt[k].tag2);
rt[k<<1].sum%=mod;
rt[k<<1].tag1%=mod;
rt[k<<1].tag2%=mod;
//upsum(k<<1);
//下放左儿子标签
int pos=rt[k<<1|1].l-rt[k].l+1;
ll adt1=(rt[k].tag1*fbi[pos-2]+rt[k].tag2*fbi[pos-1])%mod,
adt2=(rt[k].tag1*fbi[pos-1]+rt[k].tag2*fbi[pos])%mod;
//计算右儿子前两项的增量
rt[k<<1|1].tag1+=adt1;
rt[k<<1|1].tag2+=adt2;
len=rt[k<<1|1].r-rt[k<<1|1].l+1;
rt[k<<1|1].sum+=(adt1*fbi[len]+adt2*fbi[len+1]+mod-adt2);
rt[k<<1|1].sum%=mod;
rt[k<<1|1].tag1%=mod;
rt[k<<1|1].tag2%=mod;
//下方右儿子标签
//rt[k<<1|1 sum+
//upsum(k);
rt[k].tag1=rt[k].tag2=0;
//clear
//rt[k].sum=rt[]
}
void update(int l,int r,int k){
if(l<=rt[k].l&&rt[k].r<=r){
rt[k].sum+=(sfbi[rt[k].r-l+1]-sfbi[rt[k].l-l]+mod);
rt[k].sum%=mod;
rt[k].tag1+=fbi[rt[k].l-l+1];
rt[k].tag1%=mod;
rt[k].tag2+=fbi[rt[k].l+1-l+1];
rt[k].tag2%=mod;
//upsum(k);
return;
}
down(k);
if(r>=rt[k<<1|1].l)update(l,r,k<<1|1);
if(l<=rt[k<<1].r)update(l,r,k<<1);
upsum(k);
}
ll que(int l,int r,int k){
ll ans=0;
if(l<=rt[k].l&&rt[k].r<=r){
ans+=rt[k].sum;
ans%=mod;
return ans;
}
down(k);
if(r>=rt[k<<1|1].l)ans+=que(l,r,k<<1|1),ans%=mod;
if(l<=rt[k<<1].r)ans+=que(l,r,k<<1),ans%=mod;
return ans;
}
int main(){
cin>>n>>m;
fbi[1]=fbi[2]=1;
sfbi[1]=1,sfbi[2]=2;
for(int i=3;i<=n+5;i++){
fbi[i]=fbi[i-1]+fbi[i-2];
sfbi[i]=(fbi[i]+sfbi[i-1])%mod;
fbi[i]%=mod;
}
for(int i=1;i<=n;i++)
cin>>a[i];
build(1,n,1);
for(int i=1;i<=m;i++){
int opt,l,r;
cin>>opt>>l>>r;
if(opt==1){
update(l,r,1);
}
if(opt==2){
cout<<que(l,r,1)<<"\n";
}
}
return 0;
}
回复
共 1 条回复,欢迎继续交流。
正在加载回复...