```go
package main
import (
"bufio"
"fmt"
"os"
)
const MOD int64 = 1000000000
type Node struct {
s0, s1 int64
lz0 int64
lz1 int64
}
var (
n, m int
a []int64
f []int64
seg []Node
)
func mod(x int64) int64 {
x %= MOD
if x < 0 {
x += MOD
}
return x
}
func addMod(a, b int64) int64 {
a += b
if a >= MOD {
a -= MOD
}
return a
}
func mulMod(a, b int64) int64 {
return (a * b) % MOD
}
func G(A, B, k int64) (int64, int64) {
// returns (G0,G1): G0=sum_{i=0}^{k-1} F_i*g_i, G1=sum_{i=0}^{k-1} F_{i+1}*g_i
// where g_i = A*F_{i+1} + B*F_i
// Derivations:
// G0 = A*(F_k^2 - [k==0?0:1]) + B*(F_k*F_{k-1})
// G1 = A*(F_k*F_{k+1}) + B*(F_k^2)
if k <= 0 {
return 0, 0
}
Fk := f[k]
Fk1 := f[k+1]
Fk_1 := f[k-1]
Fk2 := mulMod(Fk, Fk)
t := Fk2
if k == 1 {
t = mod(t - 1)
} else {
t = mod(t - 1)
}
// Actually for k>=1, sum_{i=0}^{k-1} F_i^2 = F_k*F_{k-1}
// and sum_{i=0}^{k-1} F_i*F_{i+1} = F_k^2 - 1
// so t = F_k^2 - 1 valid for k>=1
G0 := addMod(mulMod(A, t), mulMod(B, mulMod(Fk, Fk_1)))
G1 := addMod(mulMod(A, mulMod(Fk, Fk1)), mulMod(B, Fk2))
return G0, G1
}
func apply(p, l, r int, d0, d1 int64) {
if d0 == 0 && d1 == 0 {
return
}
len := int64(r - l + 1)
g0, g1 := G(d0, d1, len)
seg[p].s0 = addMod(seg[p].s0, g0)
seg[p].s1 = addMod(seg[p].s1, g1)
seg[p].lz0 = addMod(seg[p].lz0, d0)
seg[p].lz1 = addMod(seg[p].lz1, d1)
}
func push(p, l, r int) {
d0, d1 := seg[p].lz0, seg[p].lz1
if d0 == 0 && d1 == 0 {
return
}
if l == r {
seg[p].lz0, seg[p].lz1 = 0, 0
return
}
mid := (l + r) >> 1
left := p << 1
right := left | 1
apply(left, l, mid, d0, d1)
shift := int64(mid - l + 1)
nd0 := mod(mulMod(d0, f[shift-1]) + mulMod(d1, f[shift]))
nd1 := mod(mulMod(d0, f[shift]) + mulMod(d1, f[shift+1]))
apply(right, mid+1, r, nd0, nd1)
seg[p].lz0, seg[p].lz1 = 0, 0
}
func pull(p int) {
left := p << 1
right := left | 1
seg[p].s0 = addMod(seg[left].s0, seg[right].s0)
seg[p].s1 = addMod(seg[left].s1, seg[right].s1)
}
func build(p, l, r int) {
if l == r {
val := mod(a[l])
seg[p].s0 = val
seg[p].s1 = val
return
}
mid := (l + r) >> 1
build(p<<1, l, mid)
build(p<<1|1, mid+1, r)
pull(p)
}
func rangeAdd(p, l, r, ql, qr int, d int64) {
if ql <= l && r <= qr {
offset := int64(l - ql)
d0 := mod(mulMod(d, f[offset]))
d1 := mod(mulMod(d, f[offset+1]))
apply(p, l, r, d0, d1)
return
}
push(p, l, r)
mid := (l + r) >> 1
if ql <= mid {
rangeAdd(p<<1, l, mid, ql, qr, d)
}
if qr > mid {
rangeAdd(p<<1|1, mid+1, r, ql, qr, d)
}
pull(p)
}
func pointQuery(p, l, r, idx int) int64 {
if l == r {
return seg[p].s0
}
push(p, l, r)
mid := (l + r) >> 1
if idx <= mid {
return pointQuery(p<<1, l, mid, idx)
}
return pointQuery(p<<1|1, mid+1, r, idx)
}
func pointSet(p, l, r, idx int, v int64) {
if l == r {
val := mod(v)
seg[p].s0 = val
seg[p].s1 = val
seg[p].lz0, seg[p].lz1 = 0, 0
return
}
push(p, l, r)
mid := (l + r) >> 1
if idx <= mid {
pointSet(p<<1, l, mid, idx, v)
} else {
pointSet(p<<1|1, mid+1, r, idx, v)
}
pull(p)
}
func rangeQuery(p, l, r, ql, qr int) (int64, int64) {
if ql <= l && r <= qr {
return seg[p].s0, seg[p].s1
}
push(p, l, r)
mid := (l + r) >> 1
if qr <= mid {
return rangeQuery(p<<1, l, mid, ql, qr)
}
if ql > mid {
return rangeQuery(p<<1|1, mid+1, r, ql, qr)
}
s0L, s1L := rangeQuery(p<<1, l, mid, ql, qr)
s0R, s1R := rangeQuery(p<<1|1, mid+1, r, ql, qr)
shift := int64(mid - max(l, ql) + 1)
ns0R := mod(mulMod(s0R, f[shift-1]) + mulMod(s1R, f[shift]))
ns1R := mod(mulMod(s0R, f[shift]) + mulMod(s1R, f[shift+1]))
return addMod(s0L, ns0R), addMod(s1L, ns1R)
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func main() {
in := bufio.NewReaderSize(os.Stdin, 1<<20)
out := bufio.NewWriterSize(os.Stdout, 1<<20)
defer out.Flush()
fmt.Fscan(in, &n, &m)
a = make([]int64, n+1)
for i := 1; i <= n; i++ {
fmt.Fscan(in, &a[i])
}
f = make([]int64, n+3)
f[0] = 1
f[1] = 1
for i := 2; i < len(f); i++ {
f[i] = mod(f[i-1] + f[i-2])
}
seg = make([]Node, 4*(n+5))
build(1, 1, n)
for ; m > 0; m-- {
var t int
fmt.Fscan(in, &t)
if t == 1 {
var x int
var v int64
fmt.Fscan(in, &x, &v)
pointSet(1, 1, n, x, v)
} else if t == 2 {
var l, r int
fmt.Fscan(in, &l, &r)
s0, _ := rangeQuery(1, 1, n, l, r)
fmt.Fprintln(out, mod(s0))
} else {
var l, r int
var d int64
fmt.Fscan(in, &l, &r, &d)
rangeAdd(1, 1, n, l, r, mod(d))
}
}
}
```