zoukankan      html  css  js  c++  java
  • Codeforces 718C solution

                             C. Sasha and Array
     
                           time limit per test : 
    5 seconds
                         memory limit per test : 
    256 megabytes

    Description

    Sasha has an array of integers a1, a2, ..., an. You have to perform m queries. There might be queries of two types:

    1. 1 l r x — increase all integers on the segment from l to r by values x;
    2. 2 l r — find , where f(x) is the x-th Fibonacci number. As this number may be large, you only have to find it modulo 109 + 7.

    In this problem we define Fibonacci numbers as follows: f(1) = 1, f(2) = 1, f(x) = f(x - 1) + f(x - 2) for all x > 2.

    Sasha is a very talented boy and he managed to perform all queries in five seconds. Will you be able to write the program that performs as well as Sasha?

    Input

    The first line of the input contains two integers n and m (1 ≤ n ≤ 100 000, 1 ≤ m ≤ 100 000) — the number of elements in the array and the number of queries respectively.

    The next line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109).

    Then follow m lines with queries descriptions. Each of them contains integers tpi, li, ri and may be xi (1 ≤ tpi ≤ 2, 1 ≤ li ≤ ri ≤ n, 1 ≤ xi ≤ 109). Here tpi = 1 corresponds to the queries of the first type and tpi corresponds to the queries of the second type.

    It's guaranteed that the input will contains at least one query of the second type.

    Output

    For each query of the second type print the answer modulo 109 + 7.

    Example Input
    5 4
    1 1 2 1 1
    2 1 5
    1 2 4 2
    2 2 4
    2 1 5
    Example Output
    5
    7
    9
    Note

    Initially, array a is equal to 1, 1, 2, 1, 1.

    The answer for the first query of the second type is f(1) + f(1) + f(2) + f(1) + f(1) = 1 + 1 + 1 + 1 + 1 = 5.

    After the query 1 2 4 2 array a is equal to 1, 3, 4, 3, 1.

    The answer for the second query of the second type is f(3) + f(4) + f(3) = 2 + 3 + 2 = 7.

    The answer for the third query of the second type is f(1) + f(3) + f(4) + f(3) + f(1) = 1 + 2 + 3 + 2 + 1 = 9.


    没什么可说的,就是线段树维护fib递推矩阵,线段树不难写,难写的是矩阵部分,细节很多。要是封装性太强容易把代码写得很java。

      1 /* basic header */
      2 #include <iostream>
      3 #include <cstdio>
      4 #include <cstdlib>
      5 #include <string>
      6 #include <cstring>
      7 #include <cmath>
      8 #include <cstdint>
      9 #include <climits>
     10 #include <float.h>
     11 /* STL */
     12 #include <vector>
     13 #include <set>
     14 #include <map>
     15 #include <queue>
     16 #include <stack>
     17 #include <algorithm>
     18 #include <array>
     19 #include <iterator>
     20 /* define */
     21 #define ll long long
     22 #define dou double
     23 #define pb emplace_back
     24 #define mp make_pair
     25 #define fir first
     26 #define sec second
     27 #define sot(a,b) sort(a+1,a+1+b)
     28 #define rep1(i,a,b) for(int i=a;i<=b;++i)
     29 #define rep0(i,a,b) for(int i=a;i<b;++i)
     30 #define repa(i,a) for(auto &i:a)
     31 #define eps 1e-8
     32 #define int_inf 0x3f3f3f3f
     33 #define ll_inf 0x7f7f7f7f7f7f7f7f
     34 #define lson curPos<<1
     35 #define rson curPos<<1|1
     36 /* namespace */
     37 using namespace std;
     38 /* header end */
     39 
     40 const int maxn = 1e5 + 10;
     41 const int mod = 1e9 + 7;
     42 
     43 struct Matrix
     44 {
     45     ll data[2][2];
     46     Matrix()
     47     {
     48         data[0][0] = data[0][1] = data[1][0] = data[1][1] = 0;
     49     }
     50     //变为转移矩阵
     51     inline void tran()
     52     {
     53         data[0][1] = data[1][0] = data[1][1] = 1, data[0][0] = 0;
     54     }
     55     //初始化为对角矩阵
     56     inline void init()
     57     {
     58         *this = Matrix();
     59         rep1(i, 0, 1) data[i][i] = 1;
     60     }
     61     //返回矩阵第x行
     62     inline ll *operator[](int x)
     63     {
     64         return data[x];
     65     }
     66     //定义矩阵乘法
     67     inline void operator*=(Matrix &rhs)
     68     {
     69         Matrix qAns;
     70         rep1(k, 0, 1)
     71         {
     72             rep1(i, 0, 1)
     73             {
     74                 rep1(j, 0, 1)
     75                 qAns[j][i] = (qAns[j][i] + data[j][k] * rhs[k][i]) % mod;
     76             }
     77         }
     78         *this = qAns;
     79     }
     80     //矩阵快速幂
     81     inline void operator^=(int x)
     82     {
     83         Matrix base = *this, qAns;
     84         rep1(i, 0, 1) qAns[i][i] = 1;
     85         for (register int i = x; i; i >>= 1, base *= base)
     86             if (i & 1) qAns *= base;
     87         *this = qAns;
     88     }
     89     inline void operator+=(Matrix &rhs)
     90     {
     91         rep1(i, 0, 1)
     92         {
     93             rep1(j, 0, 1)
     94             {
     95                 data[i][j] = (data[i][j] + rhs[i][j]) % mod;
     96             }
     97         }
     98     }
     99     //输出
    100     inline void pr()
    101     {
    102         rep1(t, 0, 1)
    103         {
    104             rep1(i, 0, 1) printf("%d ", data[t][i]);
    105             puts("");
    106         }
    107     }
    108 } seg[maxn << 2], add[maxn << 2];
    109 
    110 int n, m;
    111 Matrix qAns, markdown;
    112 bool lazyTag[maxn << 2];
    113 
    114 inline void pushdown(int curPos)
    115 {
    116     if (!lazyTag[curPos]) return;
    117     seg[lson] *= add[curPos]; seg[rson] *= add[curPos];
    118     add[lson] *= add[curPos]; add[rson] *= add[curPos];
    119     lazyTag[lson] = lazyTag[rson] = 1;
    120     add[curPos].init(); lazyTag[curPos] = 0;
    121 }
    122 
    123 void build(int curPos, int curL, int curR)
    124 {
    125     if (curL == curR)
    126     {
    127         seg[curPos].tran();
    128         add[curPos].init();
    129         int tmp; scanf("%d", &tmp);
    130         seg[curPos] ^= tmp - 1;
    131         return;
    132     }
    133     int mid = (curL + curR) >> 1;
    134     add[curPos].init();
    135     build(lson, curL, mid); build(rson, mid + 1, curR);
    136     seg[curPos] = Matrix();
    137     seg[curPos] += seg[lson]; seg[curPos] += seg[rson];
    138 }
    139 
    140 void update(int curPos, int curL, int curR, int qL, int qR)
    141 {
    142     if (qL <= curL && curR <= qR)
    143     {
    144         add[curPos] *= markdown; seg[curPos] *= markdown; lazyTag[curPos] = 1;
    145         return;
    146     }
    147     int mid = (curL + curR) >> 1;
    148     pushdown(curPos);
    149     if (qL <= mid) update(lson, curL, mid, qL, qR);
    150     if (mid < qR) update(rson, mid + 1, curR, qL, qR);
    151     seg[curPos] = Matrix();
    152     seg[curPos] += seg[lson]; seg[curPos] += seg[rson];
    153 }
    154 
    155 void query(int curPos, int curL, int curR, int qL, int qR)
    156 {
    157     if (qL <= curL && curR <= qR)
    158     {
    159         qAns += seg[curPos];
    160         return;
    161     }
    162     int mid = (curL + curR) >> 1;
    163     pushdown(curPos);
    164     if (qL <= mid) query(lson, curL, mid, qL, qR);
    165     if (mid < qR) query(rson, mid + 1, curR, qL, qR);
    166     seg[curPos] = Matrix();
    167     seg[curPos] += seg[lson]; seg[curPos] += seg[rson];
    168 }
    169 
    170 int main()
    171 {
    172     scanf("%d%d", &n, &m);
    173     build(1, 1, n);
    174     rep1(cnt, 1, m)
    175     {
    176         int op; scanf("%d", &op);
    177         if (op == 1)
    178         {
    179             int x, y, t; scanf("%d%d%d", &x, &y, &t);
    180             markdown.tran(); markdown ^= t;
    181             update(1, 1, n, x, y);
    182         }
    183         else
    184         {
    185             int x, y; scanf("%d%d", &x, &y);
    186             qAns = Matrix();
    187             query(1, 1, n, x, y);
    188             printf("%lld
    ", (qAns[0][0] + qAns[0][1]) % mod);
    189         }
    190     }
    191     return 0;
    192 }
  • 相关阅读:
    C#基础:单例模式与多线程
    C#基础:线程同步
    C#基础:C#中的数据结构
    C#基础:GC中什么是代,一共分几代
    C#基础:Dispose方法和Finalize方法在何时被调用
    C#基础:.NET中GC的运行机制
    C#基础:简述.NET中堆栈和堆的特点和差异
    PLSQL_基础系列05_视图控制WITH CHECK OPTION(案例)
    PLSQL_基础系列04_时间间隔INTERVAL(案例)
    PLSQL_基础系列03_合并操作UNION / UNION ALL / MINUS / INTERSET(案例)
  • 原文地址:https://www.cnblogs.com/JHSeng/p/10771892.html
Copyright © 2011-2022 走看看