题目大意是维护一个序列,规定区间加法为给区间每个数加上对应的 \(fibnacci\) 数列的一项。
我刚拿到题想到了直接下传标记、标记永久化等一堆显然错误的算法。错误原因是标记不能合并,所以时间复杂度得不到保证。
看到一种非常神仙的做法,用到了 \(fibnacci\) 数列的一个性质:
其中如果 \(f\) 出现了负的下标也没有关系,直接按 \(f_i=f_{i+2}-f_{i+1}\) 推就行。
然后我们发现对一个区间\([l,r]\)的操作,每个位置 \(x\) 增加的值为 \(f_{x-l+1}\),直接拆开:
这样一次操作对每个点的影响就变成了常数( \(f_{-l+1}\) 和 \(f_{-l}\) )乘上一个和自身有关的东西( \(f_x\) 和 \(f_{x+1}\) ),那么我们直接维护两个标记分别记录贡献就好了。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long LL;
const int N=300009,M=1000000009;
int n,m,a[N];
LL sum[N*4],f[N*2],sf[N*2],add1[N*4],add2[N*4];
void build(int k,int l,int r)
{
if(l==r)
{
sum[k]=a[l];
return;
}
int mid=l+r>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
sum[k]=sum[k<<1]+sum[k<<1|1];
}
int t(int x) { return x+300000; }
void init()
{
scanf("%d %d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,1,n);
f[t(1)]=1;
for (int i=2;i<=n+1;i++)
f[t(i)]=(f[t(i-1)]+f[t(i-2)])%M;
for (int i=0;i>=-n-1;i--)
f[t(i)]=(f[t(i+2)]-f[t(i+1)])%M;
for (int i=1;i<=n+1;i++)
sf[t(i)]=(f[t(i)]+sf[t(i-1)])%M;
}
void Add(int k,int l,int r,LL x,LL y)
{
sum[k]=(sum[k]+x*(sf[t(r+1)]-sf[t(l)])%M+y*(sf[t(r)]-sf[t(l-1)])%M)%M;
add1[k]=(add1[k]+x)%M,add2[k]=(add2[k]+y)%M;
}
void push_down(int k,int l,int r,int mid)
{
Add(k<<1,l,mid,add1[k],add2[k]);
Add(k<<1|1,mid+1,r,add1[k],add2[k]);
add1[k]=add2[k]=0;
}
void Modify(int k,int l,int r,int x,int y)
{
if(l>=x&&r<=y)
{
Add(k,l,r,f[t(1-x)],f[t(-x)]);
return;
}
int mid=l+r>>1;
push_down(k,l,r,mid);
if(mid>=x)
Modify(k<<1,l,mid,x,y);
if(mid<y)
Modify(k<<1|1,mid+1,r,x,y);
sum[k]=(sum[k<<1]+sum[k<<1|1])%M;
}
LL Querysum(int k,int l,int r,int x,int y)
{
if(l>=x&&r<=y)
return sum[k];
int mid=l+r>>1;
LL res=0;
push_down(k,l,r,mid);
if(mid>=x)
res=(res+Querysum(k<<1,l,mid,x,y))%M;
if(mid<y)
res=(res+Querysum(k<<1|1,mid+1,r,x,y))%M;
return res;
}
void work()
{
while(m--)
{
int opt,x,y;
scanf("%d %d %d",&opt,&x,&y);
if(opt==1)
Modify(1,1,n,x,y);
else
printf("%lld\n",(Querysum(1,1,n,x,y)+M)%M);
}
}
int main()
{
init();
work();
return 0;
}
CF446C DZY Loves Fibonacci Numbers
原文:https://www.cnblogs.com/With-penguin/p/13190820.html