\(\text{Problem}\)

\(\text{Solution}\)

\(\text{Fibonacci}\) 数列有一个性质:若 \(H_1=a,H_2=b,H_n=H_{n-2}+H_{n-1}\)

则有 \(H_n=a\cdot F_{n-2}+b\cdot F_{n-1}\)

有了这个性质后,对一段区间加斐波那契数列后,我们可以 \(O(1)\) 知道任意一位加的数是多少(当然是预处理出斐波那契数列后)

也就是说维护这段区间前两位加的数 \({a,b}\) 即可

对于一段区间求区间和即 \(ans=a\cdot[(\sum_{i=1}^{r-l-1}F_i)+1]+b\cdot\sum_{i=1}^{r-l}F_i\)

线段树维护每段区间加的 \(a,b\) 即可

\(\text{Code}\)

#include<cstdio>
#define ls (p << 1)
#define rs (ls | 1)
typedef long long LL;
using namespace std; const int N = 1e5 + 5;
const LL P = 1e9 + 9;
int n, m;
LL a[N], F[N], sF[N];
LL sum[N * 4], tg1[N * 4], tg2[N * 4]; void pushup(int p) {sum[p] = (sum[ls] + sum[rs]) % P;}
void update1(int l, int r, int p, int x, int v)
{
if (l == r) return void(tg1[p] = sum[p] = v);
int mid = (l + r) >> 1;
if (x <= mid) update1(l, mid, ls, x, v);
else update1(mid + 1, r, rs, x, v);
pushup(p);
}
void change(int l, int r, int p, LL v1, LL v2)
{
sum[p] = (sum[p] + v1 * (sF[(r - l - 1)<0?0:(r - l - 1)] + 1) % P + v2 * sF[r - l] % P) % P;
tg1[p] = (tg1[p] + v1) % P, tg2[p] = (tg2[p] + v2) % P;
}
void pushdown(int l, int r, int p)
{
if (!tg1[p] && !tg2[p]) return;
int mid = (l + r) >> 1;
change(l, mid, ls, tg1[p], tg2[p]);
LL v1 = (tg1[p] * F[mid - l] % P + tg2[p] * F[mid - l + 1] % P) % P;
LL v2 = (tg1[p] * F[mid - l + 1] % P + tg2[p] * F[mid - l + 2] % P) % P;
change(mid + 1, r, rs, v1, v2);
tg1[p] = 0, tg2[p] = 0;
}
void update2(int l, int r, int p, int x, int y, LL v1, LL v2)
{
if (x <= l && r <= y) return void(change(l, r, p, v1, v2));
int mid = (l + r) >> 1;
pushdown(l, r, p);
if (x <= mid) update2(l, mid, ls, x, y, v1, v2);
LL a = v1, b = v2;
if (l <= x && x <= mid) a = (v1 * F[mid - x] % P + v2 * F[mid - x + 1] % P) % P,
b = (v1 * F[mid - x + 1] % P + v2 * F[mid - x + 2] % P) % P;
else if (l > x && x <= mid) a = (v1 * F[mid - l] % P + v2 * F[mid - l + 1] % P) % P,
b = (v1 * F[mid - l + 1] % P + v2 * F[mid - l + 2] % P) % P;
if (y > mid) update2(mid + 1, r, rs, x, y, a, b);
pushup(p);
}
LL query(int l, int r, int p, int x, int y)
{
if (x <= l && r <= y) return sum[p];
int mid = (l + r) >> 1; LL ret = 0;
pushdown(l, r, p);
if (x <= mid) ret = query(l, mid, ls, x, y);
if (y > mid) ret = (ret + query(mid + 1, r, rs, x, y)) % P;
return ret;
} int main()
{
scanf("%d%d", &n, &m);
for(int i = 1, x; i <= n; i++) scanf("%d", &x), update1(1, n, 1, i, x);
F[1] = 1, F[2] = 1, sF[1] = 1, sF[2] = 2;
for(int i = 3; i <= n; i++) F[i] = (F[i - 1] + F[i - 2]) % P;
for(int i = 3; i <= n; i++) sF[i] = (sF[i - 1] + F[i]) % P;
for(int op, l, r; m; --m)
{
scanf("%d%d%d", &op, &l, &r);
if (op == 1) update2(1, n, 1, l, r, F[1], F[2]);
else printf("%lld\n", query(1, n, 1, l, r));
}
}

最新文章

  1. 《利用python进行数据分析》读书笔记 --第一、二章 准备与例子
  2. PYTHON学习之路_PYTHON基础(6)
  3. org.apache.catalina.LifecycleException
  4. vijos 1779 国王游戏
  5. leetcode 115 Distinct Subsequences ----- java
  6. 串口总是报&#39;Error opening serial port&#39;
  7. VBSCRIPT事件绑定(隐式)
  8. C# 中的值类型和引用类型
  9. 让你的javascript函数拥有记忆功能,降低全局变量的使用
  10. C#面向对象编程基础-喜课堂笔记
  11. CG中的数据变量类型
  12. ASP.NET Core实现类库项目读取配置文件
  13. Oracle内连接、外连接、右外连接、全外连接小总结
  14. rapid7/metasploitable3 CTF摘要
  15. 微信公共号:CTO技术总监
  16. ImageMagick、imagick和ghostscript三者的关联
  17. 前端 HTML标签属性
  18. Junit Framework -TestRule,自动化测试中如何再次运行失败的测试用例
  19. ORACLE官网下载登陆账号能够使用
  20. knockout示例

热门文章

  1. SqlServer 联合Update
  2. 解决一个mysql报错
  3. 爬虫之xpath插件下载与安装
  4. SpringMVC01:入门、请求参数绑定、自定义类型转换器、常见注解
  5. Maven工程卡在Resolving Maven dependencies,长时间不变
  6. hyperf 配置 https 访问
  7. java中的复合赋值运算符
  8. week_7
  9. electron中使用adm-zip将多个excel文件压缩进文件夹,使用XLSX以及XLSXStyle生成带样式excel文件
  10. MongoDB从入门到实战之MongoDB工作常用操作命令