#include <bits/stdc++.h>   using namespace std;   const int N = 200020, P = 1000000000;   int add(int a, int b) { return a + b >= P ? a + b - P : a + b; }   struct mat {     int r, c, a[2][2];     void construct(int r_, int c_) {       r = r_, c = c_;       for (int i = 0; i < r; ++i)         for (int j = 0; j < c; ++j) a[i][j] = 0;     }     mat operator*(const mat& rhs) const {       mat res;       res.construct(r, rhs.c);       for (int i = 0; i < res.r; ++i)         for (int j = 0; j < res.c; ++j)           for (int k = 0; k < c; ++k)             res.a[i][j] = add(res.a[i][j], (long long)a[i][k] * rhs.a[k][j] % P);       return res;     }   } trans_sum[N];   mat qpow(mat t, int k) {     mat res = t;     --k;     for (; k; k >>= 1) {       if (k & 1) res = res * t;       t = t * t;     }     return res;   }   mat trans;   struct node {     mat v;     int sz;     int tag;   } t[N << 2];   int n, m, a[N], fibo[N], sfibo[N];   node merge(node x, node y) {     node res;     res.sz = x.sz + y.sz;     mat nxt = y.v * trans_sum[x.sz];     res.v.construct(1, 2);     res.v.a[0][0] = add(x.v.a[0][0], nxt.a[0][0]);     res.v.a[0][1] = add(x.v.a[0][1], nxt.a[0][1]);     res.tag = 0;     return res;   }   void build(int p, int l, int r) {     t[p].tag = 0;     if (l == r) {       t[p].v.construct(1, 2);       t[p].v.a[0][0] = t[p].v.a[0][1] = a[l];       t[p].sz = 1;       return;     }     int mid = (l + r) >> 1;     build(p << 1, l, mid);     build(p << 1 | 1, mid + 1, r);     t[p] = merge(t[p << 1], t[p << 1 | 1]);   }   void ontag(int p, int l, int r, int v) {     t[p].tag = add(t[p].tag, v);     t[p].v.a[0][0] = add(t[p].v.a[0][0], (long long)v * sfibo[r - l] % P);     t[p].v.a[0][1] =         add(t[p].v.a[0][1], (long long)v * (sfibo[r - l + 1] - 1 + P) % P);   }   void pushdown(int p, int l, int r) {     if (t[p].tag) {       int mid = (l + r) >> 1;       ontag(p << 1, l, mid, t[p].tag);       ontag(p << 1 | 1, mid + 1, r, t[p].tag);       t[p].tag = 0;     }   }   void add(int p, int l, int r, int L, int R, int v) {     if (L <= l && r <= R) {       ontag(p, l, r, v);       return;     }     pushdown(p, l, r);     int mid = (l + r) >> 1;     if (L <= mid) add(p << 1, l, mid, L, R, v);     if (R > mid) add(p << 1 | 1, mid + 1, r, L, R, v);     t[p] = merge(t[p << 1], t[p << 1 | 1]);   }   void change(int p, int l, int r, int v, int x) {     if (l == r) {       a[l] = x;       t[p].v.construct(1, 2);       t[p].v.a[0][0] = t[p].v.a[0][1] = a[l];       t[p].sz = 1;       return;     }     pushdown(p, l, r);     int mid = (l + r) >> 1;     if (v <= mid)       change(p << 1, l, mid, v, x);     else       change(p << 1 | 1, mid + 1, r, v, x);     t[p] = merge(t[p << 1], t[p << 1 | 1]);   }   node qry(int p, int l, int r, int L, int R) {     if (L <= l && r <= R) return t[p];     pushdown(p, l, r);     int mid = (l + r) >> 1;     if (R <= mid)       return qry(p << 1, l, mid, L, R);     else if (L > mid)       return qry(p << 1 | 1, mid + 1, r, L, R);     else       return merge(qry(p << 1, l, mid, L, R), qry(p << 1 | 1, mid + 1, r, L, R));   }   int main() {     cout << fixed;     trans.construct(2, 2);     trans.a[0][1] = trans.a[1][0] = trans.a[1][1] = 1;     scanf( %d%d , &n, &m);     for (int i = 1; i <= n; ++i) scanf( %d , &a[i]);     fibo[0] = fibo[1] = sfibo[0] = 1;     sfibo[1] = 2;     for (int i = 2; i <= n; ++i) {       fibo[i] = add(fibo[i - 1], fibo[i - 2]);       sfibo[i] = add(sfibo[i - 1], fibo[i]);     }     trans_sum[1] = trans;     for (int i = 2; i <= n; ++i) trans_sum[i] = trans_sum[i - 1] * trans;     build(1, 1, n);     while (m--) {       int op, x, v, l, r, d;       scanf( %d , &op);       if (op == 1) {         scanf( %d%d , &x, &v);         change(1, 1, n, x, v);       } else if (op == 2) {         scanf( %d%d , &l, &r);         node ans = qry(1, 1, n, l, r);         printf( %d n , ans.v.a[0][0]);       } else if (op == 3) {         scanf( %d%d%d , &l, &r, &d);         add(1, 1, n, l, r, d);       }     }     return 0;   }