Codeforces Round #FF (Div. 2)E(线段树成段更新)

博客围绕斐波那契数列在数组查询中的应用展开。给定含n个整数的数组及m个查询,查询分两种类型,一是对指定区间元素加上对应斐波那契数,二是输出指定区间元素和取模结果。需根据输入数据处理并回复所有查询。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C. DZY Loves Fibonacci Numbers
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation

F1 = 1; F2 = 1; Fn = Fn - 1 + Fn - 2 (n > 2).

DZY loves Fibonacci numbers very much. Today DZY gives you an array consisting of n integers: a1, a2, ..., an. Moreover, there are mqueries, each query has one of the two types:

  1. Format of the query "l r". In reply to the query, you need to add Fi - l + 1 to each element ai, where l ≤ i ≤ r.
  2. Format of the query "l r". In reply to the query you should output the value of  modulo 1000000009 (109 + 9).

Help DZY reply to all the queries.

Input

The first line of the input contains two integers n and m (1 ≤ n, m ≤ 300000). The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109) — initial array a.

Then, m lines follow. A single line describes a single query in the format given in the statement. It is guaranteed that for each query inequality 1 ≤ l ≤ r ≤ n holds.

Output

For each query of the second type, print the value of the sum on a single line.

Sample test(s)
input
4 4
1 2 3 4
1 1 4
2 1 4
1 2 4
2 1 3
output
17
12

题意:支持两种操作,1 l r 将 ai 加上第i-l+1项Fibonacci数,l<=i<=r ,2 l r 求区间和

思路:根据Fibonacci数列的性质,只要知道前两项,那么可以O(1)得到后面任意项的Fibonacci数以及任意前多少项的和,可以用线段树维护每个线段的和以及每段的前两

            个Fibonacci数,延迟更新的是每个线段的前两个Fibonacci数(直接累加)

#include 
#include 
#include 
#include 
using namespace std;
#define lson l,m,o<<1
#define rson m+1,r,o<<1|1
#define maxn 300010
#define mod 1000000009

typedef long long ll;
ll a[maxn<<2];
ll b[maxn<<2];
ll sum[maxn<<2];
ll fibo[maxn];
ll sfibo[maxn];
int n,m;

ll addit(ll a,ll x)
{
    a+=x;
    if(a>=mod)a-=mod;
    return a;
}

void pushup(int o)
{
    sum[o]=addit(sum[o<<1],sum[o<<1|1]);
}

void build(int l,int r,int o)
{
    a[o]=b[o]=0;
    if(l==r){
        cin>>sum[o];
        return;
    }
    int m=l+r>>1;
    build(lson);
    build(rson);
    pushup(o);
}

ll chul(ll a,ll b,int n)
{
    if(n==1)return a;
    if(n==2)return b;
    return addit( fibo[n-2] * a % mod , fibo[n-1] * b % mod );
}

ll chuli(ll a,ll b,int n)
{
    if(n==1)return a;
    if(n==2)return addit(a,b);
    return addit( addit(sfibo[n-2],1) * a % mod , sfibo[n-1] * b % mod );
}

void pushdown(int o,int n)
{
    if(a[o])
    {
        int LL=n/2+n%2;
        int rr=n-LL;

        a[o<<1]=addit(a[o<<1],a[o]);
        b[o<<1]=addit(b[o<<1],b[o]);

        sum[o<<1]=addit( sum[o<<1] , chuli(a[o],b[o],LL) );

        ll x=chul(a[o],b[o],LL+1);
        ll y=chul(a[o],b[o],LL+2);

        a[o<<1|1]=addit(a[o<<1|1],x);
        b[o<<1|1]=addit(b[o<<1|1],y);

        sum[o<<1|1]=addit( sum[o<<1|1] , chuli(x,y,rr) );

        a[o]=b[o]=0;
    }
}

void update(int l,int r,int o,int L,int R)
{
    if(L<=l&&r<=R){
        ll aa=chul(1,1,l-L+1);
        ll bb=chul(1,1,l-L+2);
        a[o]=addit(a[o],aa);
        b[o]=addit(b[o],bb);
        sum[o]=addit(sum[o], chuli(aa,bb,r-l+1) );
        return;
    }
    pushdown(o,r-l+1);
    int m=l+r>>1;
    if(L<=m)update(lson,L,R);
    if(m>1;
    ll ans=0;
    pushdown(o,r-l+1);
    if(L<=m)ans=addit(ans,query(lson,L,R));
    if(m
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值