题目大意
定义Fibonacci数列为:
现有一个n个元素的数列,进行m个操作,操作类型如下:
1 L R表示给加上,其中 L<=i<=R
2 L R表示询问
1<=n, m<=10^5
【40%】n,m<=1000
暴力
【100%解法1】n,m<=10^5
考虑平衡规划(定期重构),把修改操作储存起来,储到了个修改的时候更新原序列。
修改更新原序列:每个位置维护一个二元组,表示它前一个元素的增加量,表示自己的增加量。对于第 j 个修改~,我们使,,。(这个类似于+1-1标记)。然后做一遍类似Fibonacci一样的循环:,。这样,我们就处理出了每个元素的增加量,最后。
询问:此时还剩下的修改操作在个以内,我们可以对剩下的每一个修改操作直接计算出对答案的贡献,最后加上原序列的前缀和即可。
时间复杂度
【100%解法1.5】
解法1的修改我们维护的是一个二元组,其实每个位置维护一个值就行了。这算是个优化吧。
【100%解法2】
我们要知道这么些东西:
1、若,,,则。
2、推广一下,对于、的类Fibonacci数列,满足
因此我们只需知道数列的前两项就可以快速求和。
用线段树维护区间内的数列的前两项。
时间复杂度
【100%解法3】
我们知道Fibonacci数列是有通项公式的。
科普:对于形如的递推数列,令,若该方程有两个不同的实数根和,则的通项公式一定可以表示成的形式
事实上,在本题的模意义下,。
于是任务变成维护两个等比数列。因为两个公比相同的等比数列可以直接相加,所以维护数列的首项即可。这个可以用线段树解决。
时间复杂度
解法1代码
1 |
|
解法2代码来自LZH
1 |
|
参考资料:Johann写的题解
引用:lzh大神的代码
