对于每个点距离它最近的Fibonacci数需要加多少,那么就知道一个区间需要加多少了。。
const int M=90;
const int N=100005;
ll f[100],sum[N<<2],need[N<<2];
bool lazy[N<<2];
inline ll Find(ll x){
if(x<=1) return 1;
int id=lower_bound(f,f+M,x)-f;
if(x-f[id-1]<=f[id]-x) return f[id-1];
return f[id];
}
inline void push_up(int t){
sum[t]=sum[L]+sum[R];
need[t]=need[L]+need[R];
}
inline void push_down(int t){
if(lazy[t]){
lazy[L]=lazy[R]=1;
sum[L]+=need[L];
sum[R]+=need[R];
need[L]=need[R]=0;
lazy[t]=0;
}
}
inline void build(int t,int l,int r){
sum[t]=0;lazy[t]=0;
need[t]=(r-l+1);
if(l!=r){
MID(l,r);
build(L,l,mid);
build(R,mid+1,r);
}
}
inline void add(int t,int l,int r,int x,ll v){
if(l==r){
sum[t]+=v;
need[t]=Find(sum[t])-sum[t];
return;
}
push_down(t);
MID(l,r);
if(x<=mid) add(L,l,mid,x,v);
else add(R,mid+1,r,x,v);
push_up(t);
}
inline void change(int t,int l,int r,int x,int y){
if(l>=x && r<=y){
lazy[t]=1;
sum[t]+=need[t];
need[t]=0;
return;
}
push_down(t);
MID(l,r);
if(y<=mid) change(L,l,mid,x,y);
else if(x>mid) change(R,mid+1,r,x,y);
else{
change(L,l,mid,x,mid);change(R,mid+1,r,mid+1,y);
}
push_up(t);
}
inline ll query(int t,int l,int r,int x,int y){
if(l>=x && r<=y) return sum[t];
push_down(t);
MID(l,r);
if(y<=mid) return query(L,l,mid,x,y);
else if(x>mid) return query(R,mid+1,r,x,y);
else return query(L,l,mid,x,mid)+query(R,mid+1,r,mid+1,y);
}
int n,m;
int op,x,y;
int main(){
f[0]=f[1]=1;
rep(i,2,M) f[i]=f[i-1]+f[i-2];
while(~scanf("%d%d",&n,&m)){
build(1,1,n);
while(m--){
op=input();
if(op==1){
x=input(),y=input();
add(1,1,n,x,y*1LL);
}
else if(op==3){
x=input(),y=input();
change(1,1,n,x,y);
}
else{
x=input(),y=input();
output(query(1,1,n,x,y));
}
}
}
return 0;
}