zoukankan      html  css  js  c++  java
  • 【CF446C】DZY Loves Fibonacci Numbers (线段树 + 斐波那契数列)

    Description

    看题戳我 给你一个序列,要求支持区间加斐波那契数列和区间求和。(~n leq 3 imes 10 ^ 5, ~fib_1 = fib_2 = 1~).

    Solution

    ​ 先来考虑一段斐波那契数列如何快速求和,根据性质有

    [egin {align} fib_n &= fib_{n - 1} + fib_{n - 2} \ &= fib_ {n - 2} + fib_{n - 3} + fib_{n - 2} \ &= fib_{n - 3} + fib_{n - 4} + fib_{n - 3} + fib_{n - 2} \ &= dots \ &= fib_2 + sum_{i = 1}^{n - 2} {fib_i} end {align} ]

    ​ 可以发现这里有个(~sum_{i = 1} ^ {n - 2} {fib_i}),转换一下就是(~sum_{i = 1} ^ {n}fib_i = fib_{n + 2} - fib_2).而两个斐波那契数列对应项加起来之后还是一个类斐波那契数列,记为(~S_i),设这个类斐波那契数列的起始项(S_1 = a, S_2 = b),显然有(~S_i = a imes fib_{i - 2} + b imes fib_{i - 1}).那么对于一段类斐波那契数列的求和,我们只要记起始的两项和这段数列的长度即可。现在可以用简单的线段树区间加来维护了,(~PushDown~)操作有一点细节,注意要分开算区间的前两项。具体看代码。。

    Code

    #include<bits/stdc++.h>
    #define For(i, j, k) for(int i = j; i <= k; ++i)
    #define Forr(i, j, k) for(int i = j; i >= k; --i)
    using namespace std;
    
    inline int read() {
    	int x = 0, p = 1; char c = getchar();
    	for(; !isdigit(c); c = getchar()) if(c == '-') p = -1;
    	for(; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    	return x *= p;
    }
    
    inline void File() {
    	freopen("cf446c.in", "r", stdin);
    	freopen("cf446c.out", "w", stdout);
    }
    
    const int N = 3e5 + 10, mod = 1e9 + 9;
    int n, m, fib[N];
    
    inline int add(int a, int b) { return (a += b) >= mod ? a - mod : a; }
    
    namespace SGT {
    #define lc (rt << 1)
    #define rc (rt << 1 | 1)
    #define mid (l + r >> 1)
    #define lson lc, l, mid
    #define rson rc, mid + 1, r
    
    	int tr[N << 2], t1[N << 2], t2[N << 2];
    	
    	inline void pushup(int rt) { tr[rt] = (tr[lc] + tr[rc]) % mod; }
    
    	inline int S(int a, int b, int x) {
    		return x == 1 ? a : (x == 2 ? b : (1ll * a * fib[x - 2] + 1ll * b * fib[x - 1]) % mod);	
    	} 
    
    	inline int sum(int a, int b, int x) {
    		return x == 1 ? a : (x == 2 ? add(a, b) : (S(a, b, x + 2) - b + mod) % mod); 	
    	}
    
    	inline void pushdown(int rt, int l, int r) {
    		if (t1[rt]) {
    			t1[lc] = add(t1[lc], t1[rt]), t2[lc] = add(t2[lc], t2[rt]);
    			tr[lc] = add(tr[lc], sum(t1[rt], t2[rt], mid - l + 1));		
    			int T1 = S(t1[rt], t2[rt], mid - l + 2), T2 = S(t1[rt], t2[rt], mid - l + 3);
    			t1[rc] = add(t1[rc], T1), t2[rc] = add(t2[rc], T2);
    			tr[rc] = add(tr[rc], sum(T1, T2, r - mid));
    			t1[rt] = t2[rt] = 0;
    		}
    	}
    
    	inline void build(int rt, int l, int r) {
    		if (l == r) tr[rt] = read();
    		else build(lson), build(rson), pushup(rt);
    	}
    
    	inline void update(int rt, int l, int r, int L, int R) {
    		if (L <= l && r <= R) {
    			tr[rt] = add(tr[rt], sum(fib[l - L + 1], fib[l - L + 2], r - l + 1));
    			t1[rt] = add(t1[rt], fib[l - L + 1]); t2[rt] = add(t2[rt], fib[l - L + 2]); 
    			return ;
    		}	
    		pushdown(rt, l, r);
    		if (L <= mid) update(lson, L, R);
    		if (R > mid) update(rson, L, R);
    		pushup(rt);
    	}
    
    	inline int query(int rt, int l, int r, int L, int R) {
    		if (L <= l && r <= R) return tr[rt];
    		pushdown(rt, l, r); int res = 0;
    		if (L <= mid) res = add(res, query(lson, L, R));
    		if (R > mid) res = add(res, query(rson, L, R));
    		return pushup(rt), res;
    	}
    
    #undef lc
    #undef rc
    #undef mid
    #undef lson
    #undef rson
    }
    
    int main() {
    	File();
    	n = read(), m = read();
    	fib[1] = fib[2] = 1; 
    	For(i, 3, n + 5) fib[i] = (fib[i - 1] + fib[i - 2]) % mod;
    
    	using namespace SGT;
    	build(1, 1, n);
    	while (m --) {
    		int opt = read(), l = read(), r = read();
    		opt == 1 ? update(1, 1, n, l, r), 1 : printf("%d
    ", query(1, 1, n, l, r)), 1;
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    Java中内部类中使用外面变量为什么final修饰?
    Java正则表达式
    Java内部类复习
    MyEclipse建立SpringMVC入门HelloWorld项目
    java中的System类
    java 中的Scanner
    Freemarker判断是否为空
    HQL多种查询实现
    查询功能实现
    EF生成 类型“System.Data.Entity.DbContext”在未被引用的程序集中定义
  • 原文地址:https://www.cnblogs.com/LSTete/p/9533089.html
Copyright © 2011-2022 走看看