package main

import (
	"bufio"
	"fmt"
	"io"
	"math/rand"
	"os"
	"time"
)

const (
	mod    int64 = 1e9 + 9
	maxn   int   = 1e5 + 5
	poolSz int   = 8e6
)

var bpow [maxn]int64

// Treap begin

const empty = 0

var (
	ptr      = 1
	usedCntr = 1
	p        [poolSz]struct {
		val, hash  int
		prio       int
		lt, rt, sz int
		used       int
	}
)

func newTreapNode(val int) int {
	for p[ptr].used == usedCntr {
		ptr++
	}
	p[ptr].val = val
	p[ptr].hash = val
	p[ptr].prio = rand.Int()
	p[ptr].sz = 1
	p[ptr].lt = empty
	p[ptr].rt = empty
	ptr++
	return ptr - 1
}

func copyNode(i int) int {
	for p[ptr].used == usedCntr {
		ptr++
	}
	p[ptr] = p[i]
	ptr++
	return ptr - 1
}

func update(i int) {
	if i == empty {
		return
	}
	lsz := p[p[i].lt].sz
	p[i].sz = lsz + 1 + p[p[i].rt].sz
	p[i].hash =
		int((int64(p[p[i].lt].hash) +
			int64(p[i].val)*bpow[lsz] +
			int64(p[p[i].rt].hash)*bpow[lsz+1]) % mod)
}

func merge(lt, rt int) (i int) {
	if lt == empty {
		return rt
	}
	if rt == empty {
		return lt
	}
	if p[lt].prio > p[rt].prio {
		i = copyNode(lt)
		p[i].rt = merge(p[i].rt, rt)
	} else {
		i = copyNode(rt)
		p[i].lt = merge(lt, p[i].lt)
	}
	update(i)
	return
}

func split(i, pos int) (lt, rt int) {
	if i == empty {
		return empty, empty
	}
	lsz := p[p[i].lt].sz
	i = copyNode(i)
	if pos <= lsz {
		lt, p[i].lt = split(p[i].lt, pos)
		rt = i
	} else {
		p[i].rt, rt = split(p[i].rt, pos-lsz-1)
		lt = i
	}
	update(i)
	return
}

func prefixHash(i, r int) int64 {
	if i == empty {
		return 0
	}
	if r > p[i].sz {
		return int64(p[i].hash)
	}
	res := prefixHash(p[i].lt, r)
	lsz := p[p[i].lt].sz
	if r > lsz {
		res = (res + int64(p[i].val)*bpow[lsz] +
			prefixHash(p[i].rt, r-lsz-1)*bpow[lsz+1]) % mod
	}
	return res
}

func almostFull() bool {
	return ptr+maxn/100 > poolSz
}

func reset() {
	usedCntr++
	ptr = 1
}

func markUsed(i int) {
	if i == empty || p[i].used == usedCntr {
		return
	}
	p[i].used = usedCntr
	markUsed(p[i].lt)
	markUsed(p[i].rt)
}

// Treap end

// SegTree begin

type node struct {
	lt, rt int
	bad    bool
}

var defaultNode = newNode(empty, empty, false)

func newNode(lt, rt int, bad bool) *node {
	return &node{lt, rt, bad}
}

func mergeNodes(lt, rt *node) *node {
	if lt.bad || rt.bad {
		return newNode(empty, empty, true)
	}
	lrsz, rlsz := p[lt.rt].sz, p[rt.lt].sz
	mn := rlsz
	if lrsz < rlsz {
		mn = lrsz
	}
	lrhash := prefixHash(lt.rt, mn)
	rlhash := prefixHash(rt.lt, mn)
	if lrhash != rlhash {
		return newNode(empty, empty, true)
	}
	new := newNode(lt.lt, rt.rt, false)
	if mn == lrsz {
		_, nlr := split(rt.lt, mn)
		new.lt = merge(new.lt, nlr)
	} else {
		_, nrl := split(lt.rt, mn)
		new.rt = merge(new.rt, nrl)
	}
	return new
}

type segTree struct {
	n    int
	tree []*node
}

func newSegTree(n int) *segTree {
	t := &segTree{}
	t.n = 1
	for t.n < n {
		t.n *= 2
	}
	t.tree = make([]*node, t.n*2)
	for i := range t.tree {
		t.tree[i] = defaultNode
	}
	return t
}

func (t *segTree) maybeFree() {
	if almostFull() {
		reset()
		for _, n := range t.tree[1:] {
			markUsed(n.lt)
			markUsed(n.rt)
		}
	}
}

func (t *segTree) update(i, v int) {
	t.maybeFree()
	if v > 0 {
		t.tree[i+t.n] = newNode(empty, newTreapNode(v), false)
	} else {
		t.tree[i+t.n] = newNode(newTreapNode(-v), empty, false)
	}
	for i = (i + t.n) / 2; i > 0; i /= 2 {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
}

func (t *segTree) query(i, j int) bool {
	t.maybeFree()
	lt, rt := defaultNode, defaultNode
	for i, j := i+t.n, j+t.n; i <= j; i, j = (i+1)/2, (j-1)/2 {
		if i%2 == 1 {
			lt = mergeNodes(lt, t.tree[i])
		}
		if j%2 == 0 {
			rt = mergeNodes(t.tree[j], rt)
		}
	}
	res := mergeNodes(lt, rt)
	return !res.bad && p[res.lt].sz == 0 && p[res.rt].sz == 0
}

// SegTree end

func init() {
	rand.Seed(time.Now().Unix())
	base := int64(rand.Intn(int(mod)-maxn) + maxn)
	bpow[0] = 1
	for i := 1; i < maxn; i++ {
		bpow[i] = bpow[i-1] * base % mod
	}
}

func main() {
	io := newFastIO(os.Stdin, os.Stdout)
	defer io.Flush()

	n, _ := io.nextInt(), io.nextInt()
	a := io.nextInts(n)

	st := newSegTree(n)
	for i := 0; i < n; i++ {
		st.update(i, a[i])
	}

	q := io.nextInt()
	for ; q > 0; q-- {
		typ := io.nextInt()
		if typ == 1 {
			i, t := io.nextInt()-1, io.nextInt()
			st.update(i, t)
		} else {
			l, r := io.nextInt()-1, io.nextInt()-1
			if st.query(l, r) {
				io.println("Yes")
			} else {
				io.println("No")
			}
		}
	}
}

type fastIO struct {
	*bufio.Reader
	*bufio.Writer
	p [1]byte
}

func newFastIO(r io.Reader, w io.Writer) *fastIO {
	return &fastIO{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)}
}

func (f *fastIO) nextInt() int {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	neg := false
	if f.p[0] == '-' {
		neg = true
		f.Read(f.p[:])
	}
	n := 0
	for '0' <= f.p[0] && f.p[0] <= '9' {
		n = n*10 + int(f.p[0]) - '0'
		f.Read(f.p[:])
	}
	if neg {
		return -n
	}
	return n
}

func (f *fastIO) nextInts(n int) []int {
	a := make([]int, n)
	for i := 0; i < n; i++ {
		a[i] = f.nextInt()
	}
	return a
}

func (f *fastIO) next() string {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	var s []byte
	for f.p[0] > ' ' {
		s = append(s, f.p[0])
		f.Read(f.p[:])
	}
	return string(s)
}

func (f *fastIO) println(a ...interface{}) {
	fmt.Fprintln(f.Writer, a...)
}

func (f *fastIO) print(a ...interface{}) {
	fmt.Fprint(f.Writer, a...)
}

func (f *fastIO) printInts(a ...int) {
	if len(a) > 0 {
		f.print(a[0])
		for _, x := range a[1:] {
			f.print(" ", x)
		}
	}
}

func (f *fastIO) printlnInts(a ...int) {
	f.printInts(a...)
	f.println()
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math/rand"
	"os"
	"time"
)

const (
	mod    int64 = 1e9 + 9
	maxn   int   = 1e5 + 5
	poolSz int   = 9e6
)

var bpow [maxn]int64

// Treap begin

type trNode struct {
	val, hash  int
	prio       int
	lt, rt, sz int
}

const empty = 0

var (
	ptr = 0
	p   [poolSz]trNode
	st  [100]int
)

func newTreapNode(val int) int {
	ptr++
	p[ptr] = trNode{val, val, rand.Int(), empty, empty, 1}
	return ptr
}

func copyNode(i int) int {
	ptr++
	p[ptr] = p[i]
	return ptr
}

func update(i int) {
	if i == empty {
		return
	}
	lsz := p[p[i].lt].sz
	p[i].sz = lsz + 1 + p[p[i].rt].sz
	p[i].hash =
		int((int64(p[p[i].lt].hash) +
			int64(p[i].val)*bpow[lsz] +
			int64(p[p[i].rt].hash)*bpow[lsz+1]) % mod)
}

func merge(lt, rt int) (i int) {
	ii := &i
	ptr := len(st)
	for lt != empty && rt != empty {
		if p[lt].prio > p[rt].prio {
			*ii = copyNode(lt)
			ptr--
			st[ptr] = *ii
			lt = p[*ii].rt
			ii = &p[*ii].rt
		} else {
			*ii = copyNode(rt)
			ptr--
			st[ptr] = *ii
			rt = p[*ii].lt
			ii = &p[*ii].lt
		}
	}
	if lt == empty {
		*ii = rt
	} else {
		*ii = lt
	}
	for _, n := range st[ptr:] {
		update(n)
	}
	return
}

func split(i, pos int) (lt, rt int) {
	l, r := &lt, &rt
	ptr := len(st)
	for i != empty && 0 < pos && pos < p[i].sz {
		i = copyNode(i)
		ptr--
		st[ptr] = i
		lsz := p[p[i].lt].sz
		if pos <= lsz {
			*r = i
			r = &p[i].lt
			i = p[i].lt
		} else {
			*l = i
			l = &p[i].rt
			i = p[i].rt
			pos -= lsz + 1
		}
	}
	if i == empty {
		*l, *r = empty, empty
	} else if pos <= 0 {
		*l, *r = empty, i
	} else if pos >= p[i].sz {
		*l, *r = i, empty
	}
	for _, n := range st[ptr:] {
		update(n)
	}
	return
}

func prefixHash(i, r int) int64 {
	if i == empty {
		return 0
	}
	if r >= p[i].sz {
		return int64(p[i].hash)
	}
	res := prefixHash(p[i].lt, r)
	lsz := p[p[i].lt].sz
	if r > lsz {
		res = (res + int64(p[i].val)*bpow[lsz] +
			prefixHash(p[i].rt, r-lsz-1)*bpow[lsz+1]) % mod
	}
	return res
}

// Treap end

// SegTree begin

type node struct {
	lt, rt int
	bad    bool
}

var defaultNode = newNode(empty, empty, false)
var badNode = newNode(empty, empty, true)

func newNode(lt, rt int, bad bool) *node {
	return &node{lt, rt, bad}
}

func mergeNodes(lt, rt *node) *node {
	if lt.bad || rt.bad {
		return badNode
	}
	lrsz, rlsz := p[lt.rt].sz, p[rt.lt].sz
	mn := rlsz
	if lrsz < rlsz {
		mn = lrsz
	}
	lrhash := prefixHash(lt.rt, mn)
	rlhash := prefixHash(rt.lt, mn)
	if lrhash != rlhash {
		return badNode
	}
	new := newNode(lt.lt, rt.rt, false)
	if mn == lrsz {
		_, nlr := split(rt.lt, mn)
		new.lt = merge(new.lt, nlr)
	} else {
		_, nrl := split(lt.rt, mn)
		new.rt = merge(new.rt, nrl)
	}
	return new
}

type segTree struct {
	n    int
	tree []*node
}

func nodeForVal(v int) *node {
	if v > 0 {
		return newNode(empty, newTreapNode(v), false)
	}
	return newNode(newTreapNode(-v), empty, false)
}

func newSegTree(a []int) *segTree {
	t := &segTree{}
	t.n = 1
	for t.n < len(a) {
		t.n *= 2
	}
	t.tree = make([]*node, t.n*2)
	for i, v := range a {
		t.tree[i+t.n] = nodeForVal(v)
	}
	for i := len(a); i < t.n; i++ {
		t.tree[i+t.n] = defaultNode
	}
	for i := t.n - 1; i > 0; i-- {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
	return t
}

func (t *segTree) update(i, v int) {
	t.tree[i+t.n] = nodeForVal(v)
	for i = (i + t.n) / 2; i > 0; i /= 2 {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
}

func (t *segTree) query(i, j int) bool {
	lt, rt := defaultNode, defaultNode
	for i, j := i+t.n, j+t.n; i <= j; i, j = (i+1)/2, (j-1)/2 {
		if i%2 == 1 {
			lt = mergeNodes(lt, t.tree[i])
		}
		if j%2 == 0 {
			rt = mergeNodes(t.tree[j], rt)
		}
	}
	res := mergeNodes(lt, rt)
	return !res.bad && p[res.lt].sz == 0 && p[res.rt].sz == 0
}

// SegTree end

func init() {
	rand.Seed(time.Now().Unix())
	base := int64(rand.Intn(int(mod)-maxn) + maxn)
	bpow[0] = 1
	for i := 1; i < maxn; i++ {
		bpow[i] = bpow[i-1] * base % mod
	}
}

// Taking some cues from ecnerwala
// https://codeforces.com/contest/1340/submission/77861280

func main() {
	io := newFastIO(os.Stdin, os.Stdout)
	defer io.Flush()

	n, _ := io.nextInt(), io.nextInt()
	a := io.nextInts(n)

	ptrInitial := ptr
	st := newSegTree(a)

	for q := io.nextInt(); q > 0; q-- {
		if ptr+400 >= poolSz {
			ptr = ptrInitial
			st = newSegTree(a)
		}
		typ := io.nextInt()
		if typ == 1 {
			i, t := io.nextInt()-1, io.nextInt()
			a[i] = t
			st.update(i, t)
		} else {
			oldPtr := ptr
			l, r := io.nextInt()-1, io.nextInt()-1
			if st.query(l, r) {
				io.println("Yes")
			} else {
				io.println("No")
			}
			ptr = oldPtr
		}
	}
}

type fastIO struct {
	*bufio.Reader
	*bufio.Writer
	p [1]byte
}

func newFastIO(r io.Reader, w io.Writer) *fastIO {
	return &fastIO{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)}
}

func (f *fastIO) nextInt() int {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	neg := false
	if f.p[0] == '-' {
		neg = true
		f.Read(f.p[:])
	}
	n := 0
	for '0' <= f.p[0] && f.p[0] <= '9' {
		n = n*10 + int(f.p[0]) - '0'
		f.Read(f.p[:])
	}
	if neg {
		return -n
	}
	return n
}

func (f *fastIO) nextInts(n int) []int {
	a := make([]int, n)
	for i := 0; i < n; i++ {
		a[i] = f.nextInt()
	}
	return a
}

func (f *fastIO) println(a ...interface{}) {
	fmt.Fprintln(f.Writer, a...)
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math/rand"
	"os"
	"time"
)

const (
	mod    int64 = 1e9 + 9
	maxn   int   = 1e5 + 5
	poolSz int   = 9e6
)

var bpow [maxn]int64

// Treap begin

type trNode struct {
	val, hash  int
	prio       int
	lt, rt, sz int
}

const empty = 0

var (
	ptr = 0
	p   [poolSz]trNode
)

func newTreapNode(val int) int {
	ptr++
	p[ptr] = trNode{val, val, rand.Int(), empty, empty, 1}
	return ptr
}

func copyNode(i int) int {
	ptr++
	p[ptr] = p[i]
	return ptr
}

func update(i int) {
	if i == empty {
		return
	}
	lsz := p[p[i].lt].sz
	p[i].sz = lsz + 1 + p[p[i].rt].sz
	p[i].hash =
		int((int64(p[p[i].lt].hash) +
			int64(p[i].val)*bpow[lsz] +
			int64(p[p[i].rt].hash)*bpow[lsz+1]) % mod)
}

func merge(lt, rt int) (i int) {
	if lt == empty {
		return rt
	}
	if rt == empty {
		return lt
	}
	if p[lt].prio > p[rt].prio {
		i = copyNode(lt)
		p[i].rt = merge(p[i].rt, rt)
	} else {
		i = copyNode(rt)
		p[i].lt = merge(lt, p[i].lt)
	}
	update(i)
	return
}

func split(i, pos int) (lt, rt int) {
	if i == empty {
		return empty, empty
	}
	if pos == 0 {
		return empty, i
	}
	if pos >= p[i].sz {
		return i, empty
	}
	lsz := p[p[i].lt].sz
	i = copyNode(i)
	if pos <= lsz {
		lt, p[i].lt = split(p[i].lt, pos)
		rt = i
	} else {
		p[i].rt, rt = split(p[i].rt, pos-lsz-1)
		lt = i
	}
	update(i)
	return
}

func prefixHash(i, r int) int64 {
	if i == empty {
		return 0
	}
	if r >= p[i].sz {
		return int64(p[i].hash)
	}
	res := prefixHash(p[i].lt, r)
	lsz := p[p[i].lt].sz
	if r > lsz {
		res = (res + int64(p[i].val)*bpow[lsz] +
			prefixHash(p[i].rt, r-lsz-1)*bpow[lsz+1]) % mod
	}
	return res
}

// Treap end

// SegTree begin

type node struct {
	lt, rt int
	bad    bool
}

var defaultNode = newNode(empty, empty, false)
var badNode = newNode(empty, empty, true)

func newNode(lt, rt int, bad bool) *node {
	return &node{lt, rt, bad}
}

func mergeNodes(lt, rt *node) *node {
	if lt.bad || rt.bad {
		return badNode
	}
	lrsz, rlsz := p[lt.rt].sz, p[rt.lt].sz
	mn := rlsz
	if lrsz < rlsz {
		mn = lrsz
	}
	lrhash := prefixHash(lt.rt, mn)
	rlhash := prefixHash(rt.lt, mn)
	if lrhash != rlhash {
		return badNode
	}
	new := newNode(lt.lt, rt.rt, false)
	if mn == lrsz {
		_, nlr := split(rt.lt, mn)
		new.lt = merge(new.lt, nlr)
	} else {
		_, nrl := split(lt.rt, mn)
		new.rt = merge(new.rt, nrl)
	}
	return new
}

type segTree struct {
	n    int
	tree []*node
}

func nodeForVal(v int) *node {
	if v > 0 {
		return newNode(empty, newTreapNode(v), false)
	}
	return newNode(newTreapNode(-v), empty, false)
}

func newSegTree(a []int) *segTree {
	t := &segTree{}
	t.n = 1
	for t.n < len(a) {
		t.n *= 2
	}
	t.tree = make([]*node, t.n*2)
	for i, v := range a {
		t.tree[i+t.n] = nodeForVal(v)
	}
	for i := len(a); i < t.n; i++ {
		t.tree[i+t.n] = defaultNode
	}
	for i := t.n - 1; i > 0; i-- {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
	return t
}

func (t *segTree) update(i, v int) {
	t.tree[i+t.n] = nodeForVal(v)
	for i = (i + t.n) / 2; i > 0; i /= 2 {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
}

func (t *segTree) query(i, j int) bool {
	lt, rt := defaultNode, defaultNode
	for i, j := i+t.n, j+t.n; i <= j; i, j = (i+1)/2, (j-1)/2 {
		if i%2 == 1 {
			lt = mergeNodes(lt, t.tree[i])
		}
		if j%2 == 0 {
			rt = mergeNodes(t.tree[j], rt)
		}
	}
	res := mergeNodes(lt, rt)
	return !res.bad && p[res.lt].sz == 0 && p[res.rt].sz == 0
}

// SegTree end

func init() {
	rand.Seed(time.Now().Unix())
	base := int64(rand.Intn(int(mod)-maxn) + maxn)
	bpow[0] = 1
	for i := 1; i < maxn; i++ {
		bpow[i] = bpow[i-1] * base % mod
	}
}

// Taking some cues from ecnerwala
// https://codeforces.com/contest/1340/submission/77861280

func main() {
	io := newFastIO(os.Stdin, os.Stdout)
	defer io.Flush()

	n, _ := io.nextInt(), io.nextInt()
	a := io.nextInts(n)

	ptrInitial := ptr
	st := newSegTree(a)

	for q := io.nextInt(); q > 0; q-- {
		if ptr+400 >= poolSz {
			ptr = ptrInitial
			st = newSegTree(a)
		}
		typ := io.nextInt()
		if typ == 1 {
			i, t := io.nextInt()-1, io.nextInt()
			a[i] = t
			st.update(i, t)
		} else {
			oldPtr := ptr
			l, r := io.nextInt()-1, io.nextInt()-1
			if st.query(l, r) {
				io.println("Yes")
			} else {
				io.println("No")
			}
			ptr = oldPtr
		}
	}
}

type fastIO struct {
	*bufio.Reader
	*bufio.Writer
	p [1]byte
}

func newFastIO(r io.Reader, w io.Writer) *fastIO {
	return &fastIO{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)}
}

func (f *fastIO) nextInt() int {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	neg := false
	if f.p[0] == '-' {
		neg = true
		f.Read(f.p[:])
	}
	n := 0
	for '0' <= f.p[0] && f.p[0] <= '9' {
		n = n*10 + int(f.p[0]) - '0'
		f.Read(f.p[:])
	}
	if neg {
		return -n
	}
	return n
}

func (f *fastIO) nextInts(n int) []int {
	a := make([]int, n)
	for i := 0; i < n; i++ {
		a[i] = f.nextInt()
	}
	return a
}

func (f *fastIO) println(a ...interface{}) {
	fmt.Fprintln(f.Writer, a...)
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math/rand"
	"os"
	"time"
)

const (
	mod    int64 = 1e9 + 9
	maxn   int   = 1e5 + 5
	poolSz int   = 8e6
)

var bpow [maxn]int64

// Treap begin

const empty = 0

var (
	ptr      = 1
	usedCntr = 1
	p        [poolSz]struct {
		val, hash  int
		prio       int
		lt, rt, sz int
		used       int
	}
)

func newTreapNode(val int) int {
	for p[ptr].used == usedCntr {
		ptr++
	}
	p[ptr].val = val
	p[ptr].hash = val
	p[ptr].prio = int(rand.Int31())
	p[ptr].sz = 1
	p[ptr].lt = empty
	p[ptr].rt = empty
	ptr++
	return ptr - 1
}

func copyNode(i int) int {
	for p[ptr].used == usedCntr {
		ptr++
	}
	p[ptr] = p[i]
	ptr++
	return ptr - 1
}

func update(i int) {
	if i == empty {
		return
	}
	lsz := p[p[i].lt].sz
	p[i].sz = lsz + 1 + p[p[i].rt].sz
	p[i].hash =
		int((int64(p[p[i].lt].hash) +
			int64(p[i].val)*bpow[lsz] +
			int64(p[p[i].rt].hash)*bpow[lsz+1]) % mod)
}

func merge(lt, rt int) (i int) {
	if lt == empty {
		return rt
	}
	if rt == empty {
		return lt
	}
	if p[lt].prio > p[rt].prio {
		i = copyNode(lt)
		p[i].rt = merge(p[i].rt, rt)
	} else {
		i = copyNode(rt)
		p[i].lt = merge(lt, p[i].lt)
	}
	update(i)
	return
}

func split(i, pos int) (lt, rt int) {
	if i == empty {
		return empty, empty
	}
	lsz := p[p[i].lt].sz
	i = copyNode(i)
	if pos <= lsz {
		lt, p[i].lt = split(p[i].lt, pos)
		rt = i
	} else {
		p[i].rt, rt = split(p[i].rt, pos-lsz-1)
		lt = i
	}
	update(i)
	return
}

func prefixHash(i, r int) int64 {
	if i == empty {
		return 0
	}
	if r > p[i].sz {
		return int64(p[i].hash)
	}
	res := prefixHash(p[i].lt, r)
	lsz := p[p[i].lt].sz
	if r > lsz {
		res = (res + int64(p[i].val)*bpow[lsz] +
			prefixHash(p[i].rt, r-lsz-1)*bpow[lsz+1]) % mod
	}
	return res
}

func almostFull() bool {
	return ptr+maxn/100 > poolSz
}

func reset() {
	usedCntr++
	ptr = 1
}

func markUsed(i int) {
	if i == empty || p[i].used == usedCntr {
		return
	}
	p[i].used = usedCntr
	markUsed(p[i].lt)
	markUsed(p[i].rt)
}

// Treap end

// SegTree begin

type node struct {
	lt, rt int
	bad    bool
}

var defaultNode = newNode(empty, empty, false)

func newNode(lt, rt int, bad bool) node {
	return node{lt, rt, bad}
}

func mergeNodes(lt, rt node) node {
	if lt.bad || rt.bad {
		return newNode(empty, empty, true)
	}
	lrsz, rlsz := p[lt.rt].sz, p[rt.lt].sz
	mn := rlsz
	if lrsz < rlsz {
		mn = lrsz
	}
	lrhash := prefixHash(lt.rt, mn)
	rlhash := prefixHash(rt.lt, mn)
	if lrhash != rlhash {
		return newNode(empty, empty, true)
	}
	new := newNode(lt.lt, rt.rt, false)
	if mn == lrsz {
		_, nlr := split(rt.lt, mn)
		new.lt = merge(new.lt, nlr)
	} else {
		_, nrl := split(lt.rt, mn)
		new.rt = merge(new.rt, nrl)
	}
	return new
}

type segTree struct {
	n    int
	tree []node
}

func newSegTree(n int) *segTree {
	t := &segTree{}
	t.n = 1
	for t.n < n {
		t.n *= 2
	}
	t.tree = make([]node, t.n*2)
	for i := range t.tree {
		t.tree[i] = defaultNode
	}
	return t
}

func (t *segTree) maybeFree() {
	if almostFull() {
		reset()
		for _, n := range t.tree[1:] {
			markUsed(n.lt)
			markUsed(n.rt)
		}
	}
}

func (t *segTree) update(i, v int) {
	t.maybeFree()
	if v > 0 {
		t.tree[i+t.n] = newNode(empty, newTreapNode(v), false)
	} else {
		t.tree[i+t.n] = newNode(newTreapNode(-v), empty, false)
	}
	for i = (i + t.n) / 2; i > 0; i /= 2 {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
}

func (t *segTree) query(i, j int) bool {
	t.maybeFree()
	lt, rt := defaultNode, defaultNode
	for i, j := i+t.n, j+t.n; i <= j; i, j = (i+1)/2, (j-1)/2 {
		if i%2 == 1 {
			lt = mergeNodes(lt, t.tree[i])
		}
		if j%2 == 0 {
			rt = mergeNodes(t.tree[j], rt)
		}
	}
	res := mergeNodes(lt, rt)
	return !res.bad && p[res.lt].sz == 0 && p[res.rt].sz == 0
}

// SegTree end

func init() {
	rand.Seed(time.Now().Unix())
	base := int64(rand.Intn(int(mod)-maxn) + maxn)
	bpow[0] = 1
	for i := 1; i < maxn; i++ {
		bpow[i] = bpow[i-1] * base % mod
	}
}

func main() {
	io := newFastIO(os.Stdin, os.Stdout)
	defer io.Flush()

	n, _ := io.nextInt(), io.nextInt()
	a := io.nextInts(n)

	st := newSegTree(n)
	for i := 0; i < n; i++ {
		st.update(i, a[i])
	}

	q := io.nextInt()
	for ; q > 0; q-- {
		typ := io.nextInt()
		if typ == 1 {
			i, t := io.nextInt()-1, io.nextInt()
			st.update(i, t)
		} else {
			l, r := io.nextInt()-1, io.nextInt()-1
			if st.query(l, r) {
				io.println("Yes")
			} else {
				io.println("No")
			}
		}
	}
}

type fastIO struct {
	*bufio.Reader
	*bufio.Writer
	p [1]byte
}

func newFastIO(r io.Reader, w io.Writer) *fastIO {
	return &fastIO{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)}
}

func (f *fastIO) nextInt() int {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	neg := false
	if f.p[0] == '-' {
		neg = true
		f.Read(f.p[:])
	}
	n := 0
	for '0' <= f.p[0] && f.p[0] <= '9' {
		n = n*10 + int(f.p[0]) - '0'
		f.Read(f.p[:])
	}
	if neg {
		return -n
	}
	return n
}

func (f *fastIO) nextInts(n int) []int {
	a := make([]int, n)
	for i := 0; i < n; i++ {
		a[i] = f.nextInt()
	}
	return a
}

func (f *fastIO) next() string {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	var s []byte
	for f.p[0] > ' ' {
		s = append(s, f.p[0])
		f.Read(f.p[:])
	}
	return string(s)
}

func (f *fastIO) println(a ...interface{}) {
	fmt.Fprintln(f.Writer, a...)
}

func (f *fastIO) print(a ...interface{}) {
	fmt.Fprint(f.Writer, a...)
}

func (f *fastIO) printInts(a ...int) {
	if len(a) > 0 {
		f.print(a[0])
		for _, x := range a[1:] {
			f.print(" ", x)
		}
	}
}

func (f *fastIO) printlnInts(a ...int) {
	f.printInts(a...)
	f.println()
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math/rand"
	"os"
	"time"
)

const (
	mod    int64 = 1e9 + 9
	maxn   int   = 1e5 + 5
	poolSz int   = 9e6
)

var bpow [maxn]int64

// Treap begin

type trNode struct {
	val, hash  int
	prio       int
	lt, rt, sz int
}

const empty = 0

var (
	ptr = 0
	p   [poolSz]trNode
)

func newTreapNode(val int) int {
	ptr++
	p[ptr] = trNode{val, val, rand.Int(), empty, empty, 1}
	return ptr
}

func copyNode(i int) int {
	ptr++
	p[ptr] = p[i]
	return ptr
}

func update(i int) {
	if i == empty {
		return
	}
	lsz := p[p[i].lt].sz
	p[i].sz = lsz + 1 + p[p[i].rt].sz
	p[i].hash =
		int((int64(p[p[i].lt].hash) +
			int64(p[i].val)*bpow[lsz] +
			int64(p[p[i].rt].hash)*bpow[lsz+1]) % mod)
}

func merge(lt, rt int) (i int) {
	if lt == empty {
		return rt
	}
	if rt == empty {
		return lt
	}
	if p[lt].prio > p[rt].prio {
		i = copyNode(lt)
		p[i].rt = merge(p[i].rt, rt)
	} else {
		i = copyNode(rt)
		p[i].lt = merge(lt, p[i].lt)
	}
	update(i)
	return
}

func split(i, pos int) (lt, rt int) {
	if i == empty {
		return empty, empty
	}
	if pos == 0 {
		return empty, i
	}
	if pos >= p[i].sz {
		return i, empty
	}
	lsz := p[p[i].lt].sz
	i = copyNode(i)
	if pos <= lsz {
		lt, p[i].lt = split(p[i].lt, pos)
		rt = i
	} else {
		p[i].rt, rt = split(p[i].rt, pos-lsz-1)
		lt = i
	}
	update(i)
	return
}

func prefixHash(i, r int) int64 {
	if i == empty {
		return 0
	}
	if r >= p[i].sz {
		return int64(p[i].hash)
	}
	res := prefixHash(p[i].lt, r)
	lsz := p[p[i].lt].sz
	if r > lsz {
		res = (res + int64(p[i].val)*bpow[lsz] +
			prefixHash(p[i].rt, r-lsz-1)*bpow[lsz+1]) % mod
	}
	return res
}

// Treap end

// SegTree begin

type node struct {
	lt, rt int
	bad    bool
}

var defaultNode = newNode(empty, empty, false)
var badNode = newNode(empty, empty, true)

func newNode(lt, rt int, bad bool) *node {
	return &node{lt, rt, bad}
}

func mergeNodes(lt, rt *node) *node {
	if lt.bad || rt.bad {
		return badNode
	}
	lrsz, rlsz := p[lt.rt].sz, p[rt.lt].sz
	mn := rlsz
	if lrsz < rlsz {
		mn = lrsz
	}
	lrhash := prefixHash(lt.rt, mn)
	rlhash := prefixHash(rt.lt, mn)
	if lrhash != rlhash {
		return badNode
	}
	new := newNode(lt.lt, rt.rt, false)
	if mn == lrsz {
		_, nlr := split(rt.lt, mn)
		new.lt = merge(new.lt, nlr)
	} else {
		_, nrl := split(lt.rt, mn)
		new.rt = merge(new.rt, nrl)
	}
	return new
}

type segTree struct {
	n    int
	tree []*node
}

func nodeForVal(v int) *node {
	if v > 0 {
		return newNode(empty, newTreapNode(v), false)
	}
	return newNode(newTreapNode(-v), empty, false)
}

func newSegTree(a []int) *segTree {
	t := &segTree{}
	t.n = 1
	for t.n < len(a) {
		t.n *= 2
	}
	t.tree = make([]*node, t.n*2)
	for i, v := range a {
		t.tree[i+t.n] = nodeForVal(v)
	}
	for i := len(a); i < t.n; i++ {
		t.tree[i+t.n] = defaultNode
	}
	for i := t.n - 1; i > 0; i-- {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
	return t
}

func (t *segTree) update(i, v int) {
	if v > 0 {
		t.tree[i+t.n] = newNode(empty, newTreapNode(v), false)
	} else {
		t.tree[i+t.n] = newNode(newTreapNode(-v), empty, false)
	}
	for i = (i + t.n) / 2; i > 0; i /= 2 {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
}

func (t *segTree) query(i, j int) bool {
	lt, rt := defaultNode, defaultNode
	for i, j := i+t.n, j+t.n; i <= j; i, j = (i+1)/2, (j-1)/2 {
		if i%2 == 1 {
			lt = mergeNodes(lt, t.tree[i])
		}
		if j%2 == 0 {
			rt = mergeNodes(t.tree[j], rt)
		}
	}
	res := mergeNodes(lt, rt)
	return !res.bad && p[res.lt].sz == 0 && p[res.rt].sz == 0
}

// SegTree end

func init() {
	rand.Seed(time.Now().Unix())
	base := int64(rand.Intn(int(mod)-maxn) + maxn)
	bpow[0] = 1
	for i := 1; i < maxn; i++ {
		bpow[i] = bpow[i-1] * base % mod
	}
}

// Taking some cues from ecnerwala
// https://codeforces.com/contest/1340/submission/77861280

func main() {
	io := newFastIO(os.Stdin, os.Stdout)
	defer io.Flush()

	n, _ := io.nextInt(), io.nextInt()
	a := io.nextInts(n)

	ptrInitial := ptr
	st := newSegTree(a)

	for q := io.nextInt(); q > 0; q-- {
		if ptr+400 >= poolSz {
			ptr = ptrInitial
			st = newSegTree(a)
		}
		typ := io.nextInt()
		if typ == 1 {
			i, t := io.nextInt()-1, io.nextInt()
			a[i] = t
			st.update(i, t)
		} else {
			oldPtr := ptr
			l, r := io.nextInt()-1, io.nextInt()-1
			if st.query(l, r) {
				io.println("Yes")
			} else {
				io.println("No")
			}
			ptr = oldPtr
		}
	}
}

type fastIO struct {
	*bufio.Reader
	*bufio.Writer
	p [1]byte
}

func newFastIO(r io.Reader, w io.Writer) *fastIO {
	return &fastIO{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)}
}

func (f *fastIO) nextInt() int {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	neg := false
	if f.p[0] == '-' {
		neg = true
		f.Read(f.p[:])
	}
	n := 0
	for '0' <= f.p[0] && f.p[0] <= '9' {
		n = n*10 + int(f.p[0]) - '0'
		f.Read(f.p[:])
	}
	if neg {
		return -n
	}
	return n
}

func (f *fastIO) nextInts(n int) []int {
	a := make([]int, n)
	for i := 0; i < n; i++ {
		a[i] = f.nextInt()
	}
	return a
}

func (f *fastIO) println(a ...interface{}) {
	fmt.Fprintln(f.Writer, a...)
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math/rand"
	"os"
	"time"
)

const (
	mod    int64 = 1e9 + 9
	maxn   int   = 1e5 + 5
	poolSz int   = 8e6
)

var bpow [maxn]int64

// Treap begin

const empty = 0

var (
	ptr      = 1
	usedCntr = 1
	p        [poolSz]struct {
		val, hash  int
		prio       int
		lt, rt, sz int
		used       int
	}
)

func newTreapNode(val int) int {
	for p[ptr].used == usedCntr {
		ptr++
	}
	p[ptr].val = val
	p[ptr].hash = val
	p[ptr].prio = rand.Int()
	p[ptr].sz = 1
	p[ptr].lt = empty
	p[ptr].rt = empty
	ptr++
	return ptr - 1
}

func copyNode(i int) int {
	for p[ptr].used == usedCntr {
		ptr++
	}
	p[ptr] = p[i]
	ptr++
	return ptr - 1
}

func update(i int) {
	if i == empty {
		return
	}
	lsz := p[p[i].lt].sz
	p[i].sz = lsz + 1 + p[p[i].rt].sz
	p[i].hash =
		int((int64(p[p[i].lt].hash) +
			int64(p[i].val)*bpow[lsz] +
			int64(p[p[i].rt].hash)*bpow[lsz+1]) % mod)
}

func merge(lt, rt int) (i int) {
	if lt == empty {
		return rt
	}
	if rt == empty {
		return lt
	}
	if p[lt].prio > p[rt].prio {
		i = copyNode(lt)
		p[i].rt = merge(p[i].rt, rt)
	} else {
		i = copyNode(rt)
		p[i].lt = merge(lt, p[i].lt)
	}
	update(i)
	return
}

func split(i, pos int) (lt, rt int) {
	if i == empty {
		return empty, empty
	}
	lsz := p[p[i].lt].sz
	i = copyNode(i)
	if pos <= lsz {
		lt, p[i].lt = split(p[i].lt, pos)
		rt = i
	} else {
		p[i].rt, rt = split(p[i].rt, pos-lsz-1)
		lt = i
	}
	update(i)
	return
}

func prefixHash(i, r int) int64 {
	if i == empty {
		return 0
	}
	if r > p[i].sz {
		return int64(p[i].hash)
	}
	res := prefixHash(p[i].lt, r)
	lsz := p[p[i].lt].sz
	if r > lsz {
		res = (res + int64(p[i].val)*bpow[lsz] +
			prefixHash(p[i].rt, r-lsz-1)*bpow[lsz+1]) % mod
	}
	return res
}

func almostFull() bool {
	return ptr+maxn/100 > poolSz
}

func reset() {
	usedCntr++
	ptr = 1
}

func markUsed(i int) {
	if i == empty || p[i].used == usedCntr {
		return
	}
	p[i].used = usedCntr
	markUsed(p[i].lt)
	markUsed(p[i].rt)
}

// Treap end

// SegTree begin

type node struct {
	lt, rt int
	bad    bool
}

var defaultNode = newNode(empty, empty, false)

func newNode(lt, rt int, bad bool) node {
	return node{lt, rt, bad}
}

func mergeNodes(lt, rt node) node {
	if lt.bad || rt.bad {
		return newNode(empty, empty, true)
	}
	lrsz, rlsz := p[lt.rt].sz, p[rt.lt].sz
	mn := rlsz
	if lrsz < rlsz {
		mn = lrsz
	}
	lrhash := prefixHash(lt.rt, mn)
	rlhash := prefixHash(rt.lt, mn)
	if lrhash != rlhash {
		return newNode(empty, empty, true)
	}
	new := newNode(lt.lt, rt.rt, false)
	if mn == lrsz {
		_, nlr := split(rt.lt, mn)
		new.lt = merge(new.lt, nlr)
	} else {
		_, nrl := split(lt.rt, mn)
		new.rt = merge(new.rt, nrl)
	}
	return new
}

type segTree struct {
	n    int
	tree []node
}

func newSegTree(n int) *segTree {
	t := &segTree{}
	t.n = 1
	for t.n < n {
		t.n *= 2
	}
	t.tree = make([]node, t.n*2)
	for i := range t.tree {
		t.tree[i] = defaultNode
	}
	return t
}

func (t *segTree) maybeFree() {
	if almostFull() {
		reset()
		for _, n := range t.tree[1:] {
			markUsed(n.lt)
			markUsed(n.rt)
		}
	}
}

func (t *segTree) update(i, v int) {
	t.maybeFree()
	if v > 0 {
		t.tree[i+t.n] = newNode(empty, newTreapNode(v), false)
	} else {
		t.tree[i+t.n] = newNode(newTreapNode(-v), empty, false)
	}
	for i = (i + t.n) / 2; i > 0; i /= 2 {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
}

func (t *segTree) query(i, j int) bool {
	t.maybeFree()
	lt, rt := defaultNode, defaultNode
	for i, j := i+t.n, j+t.n; i <= j; i, j = (i+1)/2, (j-1)/2 {
		if i%2 == 1 {
			lt = mergeNodes(lt, t.tree[i])
		}
		if j%2 == 0 {
			rt = mergeNodes(t.tree[j], rt)
		}
	}
	res := mergeNodes(lt, rt)
	return !res.bad && p[res.lt].sz == 0 && p[res.rt].sz == 0
}

// SegTree end

func init() {
	rand.Seed(time.Now().Unix())
	base := int64(rand.Intn(int(mod)-maxn) + maxn)
	bpow[0] = 1
	for i := 1; i < maxn; i++ {
		bpow[i] = bpow[i-1] * base % mod
	}
}

func main() {
	io := newFastIO(os.Stdin, os.Stdout)
	defer io.Flush()

	n, _ := io.nextInt(), io.nextInt()
	a := io.nextInts(n)

	st := newSegTree(n)
	for i := 0; i < n; i++ {
		st.update(i, a[i])
	}

	q := io.nextInt()
	for ; q > 0; q-- {
		typ := io.nextInt()
		if typ == 1 {
			i, t := io.nextInt()-1, io.nextInt()
			st.update(i, t)
		} else {
			l, r := io.nextInt()-1, io.nextInt()-1
			if st.query(l, r) {
				io.println("Yes")
			} else {
				io.println("No")
			}
		}
	}
}

type fastIO struct {
	*bufio.Reader
	*bufio.Writer
	p [1]byte
}

func newFastIO(r io.Reader, w io.Writer) *fastIO {
	return &fastIO{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)}
}

func (f *fastIO) nextInt() int {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	neg := false
	if f.p[0] == '-' {
		neg = true
		f.Read(f.p[:])
	}
	n := 0
	for '0' <= f.p[0] && f.p[0] <= '9' {
		n = n*10 + int(f.p[0]) - '0'
		f.Read(f.p[:])
	}
	if neg {
		return -n
	}
	return n
}

func (f *fastIO) nextInts(n int) []int {
	a := make([]int, n)
	for i := 0; i < n; i++ {
		a[i] = f.nextInt()
	}
	return a
}

func (f *fastIO) next() string {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	var s []byte
	for f.p[0] > ' ' {
		s = append(s, f.p[0])
		f.Read(f.p[:])
	}
	return string(s)
}

func (f *fastIO) println(a ...interface{}) {
	fmt.Fprintln(f.Writer, a...)
}

func (f *fastIO) print(a ...interface{}) {
	fmt.Fprint(f.Writer, a...)
}

func (f *fastIO) printInts(a ...int) {
	if len(a) > 0 {
		f.print(a[0])
		for _, x := range a[1:] {
			f.print(" ", x)
		}
	}
}

func (f *fastIO) printlnInts(a ...int) {
	f.printInts(a...)
	f.println()
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math/rand"
	"os"
	"time"
)

const (
	mod    int64 = 1e9 + 9
	maxn   int   = 1e5 + 5
	poolSz int   = 9e6
)

var bpow [maxn]int64

// Treap begin

const empty = 0

var (
	ptr = 0
	p   [poolSz]struct {
		val, hash  int
		prio       int
		lt, rt, sz int
	}
)

func newTreapNode(val int) int {
	ptr++
	p[ptr].val = val
	p[ptr].hash = val
	p[ptr].prio = rand.Int()
	p[ptr].sz = 1
	p[ptr].lt = empty
	p[ptr].rt = empty
	return ptr
}

func copyNode(i int) int {
	ptr++
	p[ptr] = p[i]
	return ptr
}

func update(i int) {
	if i == empty {
		return
	}
	lsz := p[p[i].lt].sz
	p[i].sz = lsz + 1 + p[p[i].rt].sz
	p[i].hash =
		int((int64(p[p[i].lt].hash) +
			int64(p[i].val)*bpow[lsz] +
			int64(p[p[i].rt].hash)*bpow[lsz+1]) % mod)
}

func merge(lt, rt int) (i int) {
	if lt == empty {
		return rt
	}
	if rt == empty {
		return lt
	}
	if p[lt].prio > p[rt].prio {
		i = copyNode(lt)
		p[i].rt = merge(p[i].rt, rt)
	} else {
		i = copyNode(rt)
		p[i].lt = merge(lt, p[i].lt)
	}
	update(i)
	return
}

func split(i, pos int) (lt, rt int) {
	if i == empty {
		return empty, empty
	}
	if pos == 0 {
		return empty, i
	}
	if pos >= p[i].sz {
		return i, empty
	}
	lsz := p[p[i].lt].sz
	i = copyNode(i)
	if pos <= lsz {
		lt, p[i].lt = split(p[i].lt, pos)
		rt = i
	} else {
		p[i].rt, rt = split(p[i].rt, pos-lsz-1)
		lt = i
	}
	update(i)
	return
}

func prefixHash(i, r int) int64 {
	if i == empty {
		return 0
	}
	if r >= p[i].sz {
		return int64(p[i].hash)
	}
	res := prefixHash(p[i].lt, r)
	lsz := p[p[i].lt].sz
	if r > lsz {
		res = (res + int64(p[i].val)*bpow[lsz] +
			prefixHash(p[i].rt, r-lsz-1)*bpow[lsz+1]) % mod
	}
	return res
}

// Treap end

// SegTree begin

type node struct {
	lt, rt int
	bad    bool
}

var defaultNode = newNode(empty, empty, false)
var badNode = newNode(empty, empty, true)

func newNode(lt, rt int, bad bool) *node {
	return &node{lt, rt, bad}
}

func mergeNodes(lt, rt *node) *node {
	if lt.bad || rt.bad {
		return badNode
	}
	lrsz, rlsz := p[lt.rt].sz, p[rt.lt].sz
	mn := rlsz
	if lrsz < rlsz {
		mn = lrsz
	}
	lrhash := prefixHash(lt.rt, mn)
	rlhash := prefixHash(rt.lt, mn)
	if lrhash != rlhash {
		return badNode
	}
	new := newNode(lt.lt, rt.rt, false)
	if mn == lrsz {
		_, nlr := split(rt.lt, mn)
		new.lt = merge(new.lt, nlr)
	} else {
		_, nrl := split(lt.rt, mn)
		new.rt = merge(new.rt, nrl)
	}
	return new
}

type segTree struct {
	n    int
	tree []*node
}

func nodeForVal(v int) *node {
	if v > 0 {
		return newNode(empty, newTreapNode(v), false)
	}
	return newNode(newTreapNode(-v), empty, false)
}

func newSegTree(a []int) *segTree {
	t := &segTree{}
	t.n = 1
	for t.n < len(a) {
		t.n *= 2
	}
	t.tree = make([]*node, t.n*2)
	for i, v := range a {
		t.tree[i+t.n] = nodeForVal(v)
	}
	for i := len(a); i < t.n; i++ {
		t.tree[i+t.n] = defaultNode
	}
	for i := t.n - 1; i > 0; i-- {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
	return t
}

func (t *segTree) update(i, v int) {
	if v > 0 {
		t.tree[i+t.n] = newNode(empty, newTreapNode(v), false)
	} else {
		t.tree[i+t.n] = newNode(newTreapNode(-v), empty, false)
	}
	for i = (i + t.n) / 2; i > 0; i /= 2 {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
}

func (t *segTree) query(i, j int) bool {
	lt, rt := defaultNode, defaultNode
	for i, j := i+t.n, j+t.n; i <= j; i, j = (i+1)/2, (j-1)/2 {
		if i%2 == 1 {
			lt = mergeNodes(lt, t.tree[i])
		}
		if j%2 == 0 {
			rt = mergeNodes(t.tree[j], rt)
		}
	}
	res := mergeNodes(lt, rt)
	return !res.bad && p[res.lt].sz == 0 && p[res.rt].sz == 0
}

// SegTree end

func init() {
	rand.Seed(time.Now().Unix())
	base := int64(rand.Intn(int(mod)-maxn) + maxn)
	bpow[0] = 1
	for i := 1; i < maxn; i++ {
		bpow[i] = bpow[i-1] * base % mod
	}
}

// Taking some cues from ecnerwala
// https://codeforces.com/contest/1340/submission/77861280

func main() {
	io := newFastIO(os.Stdin, os.Stdout)
	defer io.Flush()

	n, _ := io.nextInt(), io.nextInt()
	a := io.nextInts(n)

	ptrInitial := ptr
	st := newSegTree(a)

	q := io.nextInt()
	for ; q > 0; q-- {
		if ptr+100 >= poolSz {
			ptr = ptrInitial
			st = newSegTree(a)
		}
		typ := io.nextInt()
		if typ == 1 {
			i, t := io.nextInt()-1, io.nextInt()
			a[i] = t
			st.update(i, t)
		} else {
			oldPtr := ptr
			l, r := io.nextInt()-1, io.nextInt()-1
			if st.query(l, r) {
				io.println("Yes")
			} else {
				io.println("No")
			}
			ptr = oldPtr
		}
	}
}

type fastIO struct {
	*bufio.Reader
	*bufio.Writer
	p [1]byte
}

func newFastIO(r io.Reader, w io.Writer) *fastIO {
	return &fastIO{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)}
}

func (f *fastIO) nextInt() int {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	neg := false
	if f.p[0] == '-' {
		neg = true
		f.Read(f.p[:])
	}
	n := 0
	for '0' <= f.p[0] && f.p[0] <= '9' {
		n = n*10 + int(f.p[0]) - '0'
		f.Read(f.p[:])
	}
	if neg {
		return -n
	}
	return n
}

func (f *fastIO) nextInts(n int) []int {
	a := make([]int, n)
	for i := 0; i < n; i++ {
		a[i] = f.nextInt()
	}
	return a
}

func (f *fastIO) next() string {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	var s []byte
	for f.p[0] > ' ' {
		s = append(s, f.p[0])
		f.Read(f.p[:])
	}
	return string(s)
}

func (f *fastIO) println(a ...interface{}) {
	fmt.Fprintln(f.Writer, a...)
}

func (f *fastIO) print(a ...interface{}) {
	fmt.Fprint(f.Writer, a...)
}

func (f *fastIO) printInts(a ...int) {
	if len(a) > 0 {
		f.print(a[0])
		for _, x := range a[1:] {
			f.print(" ", x)
		}
	}
}

func (f *fastIO) printlnInts(a ...int) {
	f.printInts(a...)
	f.println()
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math/rand"
	"os"
	"time"
)

const (
	mod    int64 = 1e9 + 9
	maxn   int   = 1e5 + 5
	poolSz int   = 9.5e6
)

var bpow [maxn]int64

// Treap begin

const empty = 0

var (
	ptr = 0
	p   [poolSz]struct {
		val, hash  int
		prio       int
		lt, rt, sz int
	}
)

func newTreapNode(val int) int {
	ptr++
	p[ptr].val = val
	p[ptr].hash = val
	p[ptr].prio = rand.Int()
	p[ptr].sz = 1
	p[ptr].lt = empty
	p[ptr].rt = empty
	return ptr
}

func copyNode(i int) int {
	ptr++
	p[ptr] = p[i]
	return ptr
}

func update(i int) {
	if i == empty {
		return
	}
	lsz := p[p[i].lt].sz
	p[i].sz = lsz + 1 + p[p[i].rt].sz
	p[i].hash =
		int((int64(p[p[i].lt].hash) +
			int64(p[i].val)*bpow[lsz] +
			int64(p[p[i].rt].hash)*bpow[lsz+1]) % mod)
}

func merge(lt, rt int) (i int) {
	if lt == empty {
		return rt
	}
	if rt == empty {
		return lt
	}
	if p[lt].prio > p[rt].prio {
		i = copyNode(lt)
		p[i].rt = merge(p[i].rt, rt)
	} else {
		i = copyNode(rt)
		p[i].lt = merge(lt, p[i].lt)
	}
	update(i)
	return
}

func split(i, pos int) (lt, rt int) {
	if i == empty {
		return empty, empty
	}
	if pos == 0 {
		return empty, i
	}
	if pos >= p[i].sz {
		return i, empty
	}
	lsz := p[p[i].lt].sz
	i = copyNode(i)
	if pos <= lsz {
		lt, p[i].lt = split(p[i].lt, pos)
		rt = i
	} else {
		p[i].rt, rt = split(p[i].rt, pos-lsz-1)
		lt = i
	}
	update(i)
	return
}

func prefixHash(i, r int) int64 {
	if i == empty {
		return 0
	}
	if r >= p[i].sz {
		return int64(p[i].hash)
	}
	res := prefixHash(p[i].lt, r)
	lsz := p[p[i].lt].sz
	if r > lsz {
		res = (res + int64(p[i].val)*bpow[lsz] +
			prefixHash(p[i].rt, r-lsz-1)*bpow[lsz+1]) % mod
	}
	return res
}

// Treap end

// SegTree begin

type node struct {
	lt, rt int
	bad    bool
}

var defaultNode = newNode(empty, empty, false)
var badNode = newNode(empty, empty, true)

func newNode(lt, rt int, bad bool) *node {
	return &node{lt, rt, bad}
}

func mergeNodes(lt, rt *node) *node {
	if lt.bad || rt.bad {
		return badNode
	}
	lrsz, rlsz := p[lt.rt].sz, p[rt.lt].sz
	mn := rlsz
	if lrsz < rlsz {
		mn = lrsz
	}
	lrhash := prefixHash(lt.rt, mn)
	rlhash := prefixHash(rt.lt, mn)
	if lrhash != rlhash {
		return badNode
	}
	new := newNode(lt.lt, rt.rt, false)
	if mn == lrsz {
		_, nlr := split(rt.lt, mn)
		new.lt = merge(new.lt, nlr)
	} else {
		_, nrl := split(lt.rt, mn)
		new.rt = merge(new.rt, nrl)
	}
	return new
}

type segTree struct {
	n    int
	tree []*node
}

func nodeForVal(v int) *node {
	if v > 0 {
		return newNode(empty, newTreapNode(v), false)
	}
	return newNode(newTreapNode(-v), empty, false)
}

func newSegTree(a []int) *segTree {
	t := &segTree{}
	t.n = 1
	for t.n < len(a) {
		t.n *= 2
	}
	t.tree = make([]*node, t.n*2)
	for i, v := range a {
		t.tree[i+t.n] = nodeForVal(v)
	}
	for i := len(a); i < t.n; i++ {
		t.tree[i+t.n] = defaultNode
	}
	for i := t.n - 1; i > 0; i-- {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
	return t
}

func (t *segTree) update(i, v int) {
	if v > 0 {
		t.tree[i+t.n] = newNode(empty, newTreapNode(v), false)
	} else {
		t.tree[i+t.n] = newNode(newTreapNode(-v), empty, false)
	}
	for i = (i + t.n) / 2; i > 0; i /= 2 {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
}

func (t *segTree) query(i, j int) bool {
	lt, rt := defaultNode, defaultNode
	for i, j := i+t.n, j+t.n; i <= j; i, j = (i+1)/2, (j-1)/2 {
		if i%2 == 1 {
			lt = mergeNodes(lt, t.tree[i])
		}
		if j%2 == 0 {
			rt = mergeNodes(t.tree[j], rt)
		}
	}
	res := mergeNodes(lt, rt)
	return !res.bad && p[res.lt].sz == 0 && p[res.rt].sz == 0
}

// SegTree end

func init() {
	rand.Seed(time.Now().Unix())
	base := int64(rand.Intn(int(mod)-maxn) + maxn)
	bpow[0] = 1
	for i := 1; i < maxn; i++ {
		bpow[i] = bpow[i-1] * base % mod
	}
}

// Taking some cues from ecnerwala
// https://codeforces.com/contest/1340/submission/77861280

func main() {
	io := newFastIO(os.Stdin, os.Stdout)
	defer io.Flush()

	n, _ := io.nextInt(), io.nextInt()
	a := io.nextInts(n)

	ptrInitial := ptr
	st := newSegTree(a)

	q := io.nextInt()
	for ; q > 0; q-- {
		if ptr+100 >= poolSz {
			ptr = ptrInitial
			st = newSegTree(a)
		}
		typ := io.nextInt()
		if typ == 1 {
			i, t := io.nextInt()-1, io.nextInt()
			st.update(i, t)
		} else {
			oldPtr := ptr
			l, r := io.nextInt()-1, io.nextInt()-1
			if st.query(l, r) {
				io.println("Yes")
			} else {
				io.println("No")
			}
			ptr = oldPtr
		}
	}
}

type fastIO struct {
	*bufio.Reader
	*bufio.Writer
	p [1]byte
}

func newFastIO(r io.Reader, w io.Writer) *fastIO {
	return &fastIO{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)}
}

func (f *fastIO) nextInt() int {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	neg := false
	if f.p[0] == '-' {
		neg = true
		f.Read(f.p[:])
	}
	n := 0
	for '0' <= f.p[0] && f.p[0] <= '9' {
		n = n*10 + int(f.p[0]) - '0'
		f.Read(f.p[:])
	}
	if neg {
		return -n
	}
	return n
}

func (f *fastIO) nextInts(n int) []int {
	a := make([]int, n)
	for i := 0; i < n; i++ {
		a[i] = f.nextInt()
	}
	return a
}

func (f *fastIO) next() string {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	var s []byte
	for f.p[0] > ' ' {
		s = append(s, f.p[0])
		f.Read(f.p[:])
	}
	return string(s)
}

func (f *fastIO) println(a ...interface{}) {
	fmt.Fprintln(f.Writer, a...)
}

func (f *fastIO) print(a ...interface{}) {
	fmt.Fprint(f.Writer, a...)
}

func (f *fastIO) printInts(a ...int) {
	if len(a) > 0 {
		f.print(a[0])
		for _, x := range a[1:] {
			f.print(" ", x)
		}
	}
}

func (f *fastIO) printlnInts(a ...int) {
	f.printInts(a...)
	f.println()
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math/rand"
	"os"
	"time"
)

const (
	mod    int64 = 1e9 + 9
	maxn   int   = 1e5 + 5
	poolSz int   = 8e6
)

var bpow [maxn]int64

// Treap begin

const empty = 0

var (
	ptr      = 1
	usedCntr = 1
	p        [poolSz]struct {
		val, hash  int
		prio       int
		lt, rt, sz int
		used       int
	}
)

func newTreapNode(val int) int {
	for p[ptr].used == usedCntr {
		ptr++
	}
	p[ptr].val = val
	p[ptr].hash = val
	p[ptr].prio = rand.Int()
	p[ptr].sz = 1
	p[ptr].lt = empty
	p[ptr].rt = empty
	ptr++
	return ptr - 1
}

func copyNode(i int) int {
	for p[ptr].used == usedCntr {
		ptr++
	}
	p[ptr] = p[i]
	ptr++
	return ptr - 1
}

func update(i int) {
	if i == empty {
		return
	}
	lsz := p[p[i].lt].sz
	p[i].sz = lsz + 1 + p[p[i].rt].sz
	p[i].hash =
		int((int64(p[p[i].lt].hash) +
			int64(p[i].val)*bpow[lsz] +
			int64(p[p[i].rt].hash)*bpow[lsz+1]) % mod)
}

func merge(lt, rt int) (i int) {
	if lt == empty {
		return rt
	}
	if rt == empty {
		return lt
	}
	if p[lt].prio > p[rt].prio {
		i = copyNode(lt)
		p[i].rt = merge(p[i].rt, rt)
	} else {
		i = copyNode(rt)
		p[i].lt = merge(lt, p[i].lt)
	}
	update(i)
	return
}

func split(i, pos int) (lt, rt int) {
	if i == empty {
		return empty, empty
	}
	if pos == 0 {
		return empty, i
	}
	if pos >= p[i].sz {
		return i, empty
	}
	lsz := p[p[i].lt].sz
	i = copyNode(i)
	if pos <= lsz {
		lt, p[i].lt = split(p[i].lt, pos)
		rt = i
	} else {
		p[i].rt, rt = split(p[i].rt, pos-lsz-1)
		lt = i
	}
	update(i)
	return
}

func prefixHash(i, r int) int64 {
	if i == empty {
		return 0
	}
	if r > p[i].sz {
		return int64(p[i].hash)
	}
	res := prefixHash(p[i].lt, r)
	lsz := p[p[i].lt].sz
	if r > lsz {
		res = (res + int64(p[i].val)*bpow[lsz] +
			prefixHash(p[i].rt, r-lsz-1)*bpow[lsz+1]) % mod
	}
	return res
}

func almostFull() bool {
	return ptr+maxn/100 > poolSz
}

func reset() {
	usedCntr++
	ptr = 1
}

func markUsed(i int) {
	if i == empty || p[i].used == usedCntr {
		return
	}
	p[i].used = usedCntr
	markUsed(p[i].lt)
	markUsed(p[i].rt)
}

// Treap end

// SegTree begin

type node struct {
	lt, rt int
	bad    bool
}

var defaultNode = newNode(empty, empty, false)

func newNode(lt, rt int, bad bool) *node {
	return &node{lt, rt, bad}
}

func mergeNodes(lt, rt *node) *node {
	if lt.bad || rt.bad {
		return newNode(empty, empty, true)
	}
	lrsz, rlsz := p[lt.rt].sz, p[rt.lt].sz
	mn := rlsz
	if lrsz < rlsz {
		mn = lrsz
	}
	lrhash := prefixHash(lt.rt, mn)
	rlhash := prefixHash(rt.lt, mn)
	if lrhash != rlhash {
		return newNode(empty, empty, true)
	}
	new := newNode(lt.lt, rt.rt, false)
	if mn == lrsz {
		_, nlr := split(rt.lt, mn)
		new.lt = merge(new.lt, nlr)
	} else {
		_, nrl := split(lt.rt, mn)
		new.rt = merge(new.rt, nrl)
	}
	return new
}

type segTree struct {
	n    int
	tree []*node
}

func newSegTree(n int) *segTree {
	t := &segTree{}
	t.n = 1
	for t.n < n {
		t.n *= 2
	}
	t.tree = make([]*node, t.n*2)
	for i := range t.tree {
		t.tree[i] = defaultNode
	}
	return t
}

func (t *segTree) maybeFree() {
	if almostFull() {
		reset()
		for _, n := range t.tree[1:] {
			markUsed(n.lt)
			markUsed(n.rt)
		}
	}
}

func (t *segTree) update(i, v int) {
	t.maybeFree()
	if v > 0 {
		t.tree[i+t.n] = newNode(empty, newTreapNode(v), false)
	} else {
		t.tree[i+t.n] = newNode(newTreapNode(-v), empty, false)
	}
	for i = (i + t.n) / 2; i > 0; i /= 2 {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
}

func (t *segTree) query(i, j int) bool {
	t.maybeFree()
	lt, rt := defaultNode, defaultNode
	for i, j := i+t.n, j+t.n; i <= j; i, j = (i+1)/2, (j-1)/2 {
		if i%2 == 1 {
			lt = mergeNodes(lt, t.tree[i])
		}
		if j%2 == 0 {
			rt = mergeNodes(t.tree[j], rt)
		}
	}
	res := mergeNodes(lt, rt)
	return !res.bad && p[res.lt].sz == 0 && p[res.rt].sz == 0
}

// SegTree end

func init() {
	rand.Seed(time.Now().Unix())
	base := int64(rand.Intn(int(mod)-maxn) + maxn)
	bpow[0] = 1
	for i := 1; i < maxn; i++ {
		bpow[i] = bpow[i-1] * base % mod
	}
}

func main() {
	io := newFastIO(os.Stdin, os.Stdout)
	defer io.Flush()

	n, _ := io.nextInt(), io.nextInt()
	a := io.nextInts(n)

	st := newSegTree(n)
	for i := 0; i < n; i++ {
		st.update(i, a[i])
	}

	q := io.nextInt()
	for ; q > 0; q-- {
		typ := io.nextInt()
		if typ == 1 {
			i, t := io.nextInt()-1, io.nextInt()
			st.update(i, t)
		} else {
			l, r := io.nextInt()-1, io.nextInt()-1
			if st.query(l, r) {
				io.println("Yes")
			} else {
				io.println("No")
			}
		}
	}
}

type fastIO struct {
	*bufio.Reader
	*bufio.Writer
	p [1]byte
}

func newFastIO(r io.Reader, w io.Writer) *fastIO {
	return &fastIO{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)}
}

func (f *fastIO) nextInt() int {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	neg := false
	if f.p[0] == '-' {
		neg = true
		f.Read(f.p[:])
	}
	n := 0
	for '0' <= f.p[0] && f.p[0] <= '9' {
		n = n*10 + int(f.p[0]) - '0'
		f.Read(f.p[:])
	}
	if neg {
		return -n
	}
	return n
}

func (f *fastIO) nextInts(n int) []int {
	a := make([]int, n)
	for i := 0; i < n; i++ {
		a[i] = f.nextInt()
	}
	return a
}

func (f *fastIO) next() string {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	var s []byte
	for f.p[0] > ' ' {
		s = append(s, f.p[0])
		f.Read(f.p[:])
	}
	return string(s)
}

func (f *fastIO) println(a ...interface{}) {
	fmt.Fprintln(f.Writer, a...)
}

func (f *fastIO) print(a ...interface{}) {
	fmt.Fprint(f.Writer, a...)
}

func (f *fastIO) printInts(a ...int) {
	if len(a) > 0 {
		f.print(a[0])
		for _, x := range a[1:] {
			f.print(" ", x)
		}
	}
}

func (f *fastIO) printlnInts(a ...int) {
	f.printInts(a...)
	f.println()
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math/rand"
	"os"
	"time"
)

const (
	mod    int64 = 1e9 + 9
	maxn   int   = 1e5 + 5
	poolSz int   = 9e6
)

var bpow [maxn]int64

// Treap begin

type trNode struct {
	val, hash  int
	prio       int
	lt, rt, sz int
}

const empty = 0

var (
	ptr = 0
	p   [poolSz]trNode
)

func newTreapNode(val int) int {
	ptr++
	p[ptr] = trNode{val, val, rand.Int(), empty, empty, 1}
	return ptr
}

func copyNode(i int) int {
	ptr++
	p[ptr] = p[i]
	return ptr
}

func update(i int) {
	if i == empty {
		return
	}
	lsz := p[p[i].lt].sz
	p[i].sz = lsz + 1 + p[p[i].rt].sz
	p[i].hash =
		int((int64(p[p[i].lt].hash) +
			int64(p[i].val)*bpow[lsz] +
			int64(p[p[i].rt].hash)*bpow[lsz+1]) % mod)
}

func merge(lt, rt int) (i int) {
	ii := &i
	for lt != empty && rt != empty {
		if p[lt].prio > p[rt].prio {
			*ii = copyNode(lt)
			defer update(*ii)
			lt = p[*ii].rt
			ii = &p[*ii].rt
		} else {
			*ii = copyNode(rt)
			defer update(*ii)
			rt = p[*ii].lt
			ii = &p[*ii].lt
		}
	}
	if lt == empty {
		*ii = rt
	} else {
		*ii = lt
	}
	return
}

func split(i, pos int) (lt, rt int) {
	l, r := &lt, &rt
	for i != empty && 0 < pos && pos < p[i].sz {
		i = copyNode(i)
		defer update(i)
		lsz := p[p[i].lt].sz
		if pos <= lsz {
			*r = i
			r = &p[i].lt
			i = p[i].lt
		} else {
			*l = i
			l = &p[i].rt
			i = p[i].rt
			pos -= lsz + 1
		}
	}
	if i == empty {
		*l, *r = empty, empty
	} else if pos <= 0 {
		*l, *r = empty, i
	} else if pos >= p[i].sz {
		*l, *r = i, empty
	}
	return
}

func prefixHash(i, r int) int64 {
	if i == empty {
		return 0
	}
	if r >= p[i].sz {
		return int64(p[i].hash)
	}
	res := prefixHash(p[i].lt, r)
	lsz := p[p[i].lt].sz
	if r > lsz {
		res = (res + int64(p[i].val)*bpow[lsz] +
			prefixHash(p[i].rt, r-lsz-1)*bpow[lsz+1]) % mod
	}
	return res
}

// Treap end

// SegTree begin

type node struct {
	lt, rt int
	bad    bool
}

var defaultNode = newNode(empty, empty, false)
var badNode = newNode(empty, empty, true)

func newNode(lt, rt int, bad bool) *node {
	return &node{lt, rt, bad}
}

func mergeNodes(lt, rt *node) *node {
	if lt.bad || rt.bad {
		return badNode
	}
	lrsz, rlsz := p[lt.rt].sz, p[rt.lt].sz
	mn := rlsz
	if lrsz < rlsz {
		mn = lrsz
	}
	lrhash := prefixHash(lt.rt, mn)
	rlhash := prefixHash(rt.lt, mn)
	if lrhash != rlhash {
		return badNode
	}
	new := newNode(lt.lt, rt.rt, false)
	if mn == lrsz {
		_, nlr := split(rt.lt, mn)
		new.lt = merge(new.lt, nlr)
	} else {
		_, nrl := split(lt.rt, mn)
		new.rt = merge(new.rt, nrl)
	}
	return new
}

type segTree struct {
	n    int
	tree []*node
}

func nodeForVal(v int) *node {
	if v > 0 {
		return newNode(empty, newTreapNode(v), false)
	}
	return newNode(newTreapNode(-v), empty, false)
}

func newSegTree(a []int) *segTree {
	t := &segTree{}
	t.n = 1
	for t.n < len(a) {
		t.n *= 2
	}
	t.tree = make([]*node, t.n*2)
	for i, v := range a {
		t.tree[i+t.n] = nodeForVal(v)
	}
	for i := len(a); i < t.n; i++ {
		t.tree[i+t.n] = defaultNode
	}
	for i := t.n - 1; i > 0; i-- {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
	return t
}

func (t *segTree) update(i, v int) {
	t.tree[i+t.n] = nodeForVal(v)
	for i = (i + t.n) / 2; i > 0; i /= 2 {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
}

func (t *segTree) query(i, j int) bool {
	lt, rt := defaultNode, defaultNode
	for i, j := i+t.n, j+t.n; i <= j; i, j = (i+1)/2, (j-1)/2 {
		if i%2 == 1 {
			lt = mergeNodes(lt, t.tree[i])
		}
		if j%2 == 0 {
			rt = mergeNodes(t.tree[j], rt)
		}
	}
	res := mergeNodes(lt, rt)
	return !res.bad && p[res.lt].sz == 0 && p[res.rt].sz == 0
}

// SegTree end

func init() {
	rand.Seed(time.Now().Unix())
	base := int64(rand.Intn(int(mod)-maxn) + maxn)
	bpow[0] = 1
	for i := 1; i < maxn; i++ {
		bpow[i] = bpow[i-1] * base % mod
	}
}

// Taking some cues from ecnerwala
// https://codeforces.com/contest/1340/submission/77861280

func main() {
	io := newFastIO(os.Stdin, os.Stdout)
	defer io.Flush()

	n, _ := io.nextInt(), io.nextInt()
	a := io.nextInts(n)

	ptrInitial := ptr
	st := newSegTree(a)

	for q := io.nextInt(); q > 0; q-- {
		if ptr+400 >= poolSz {
			ptr = ptrInitial
			st = newSegTree(a)
		}
		typ := io.nextInt()
		if typ == 1 {
			i, t := io.nextInt()-1, io.nextInt()
			a[i] = t
			st.update(i, t)
		} else {
			oldPtr := ptr
			l, r := io.nextInt()-1, io.nextInt()-1
			if st.query(l, r) {
				io.println("Yes")
			} else {
				io.println("No")
			}
			ptr = oldPtr
		}
	}
}

type fastIO struct {
	*bufio.Reader
	*bufio.Writer
	p [1]byte
}

func newFastIO(r io.Reader, w io.Writer) *fastIO {
	return &fastIO{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)}
}

func (f *fastIO) nextInt() int {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	neg := false
	if f.p[0] == '-' {
		neg = true
		f.Read(f.p[:])
	}
	n := 0
	for '0' <= f.p[0] && f.p[0] <= '9' {
		n = n*10 + int(f.p[0]) - '0'
		f.Read(f.p[:])
	}
	if neg {
		return -n
	}
	return n
}

func (f *fastIO) nextInts(n int) []int {
	a := make([]int, n)
	for i := 0; i < n; i++ {
		a[i] = f.nextInt()
	}
	return a
}

func (f *fastIO) println(a ...interface{}) {
	fmt.Fprintln(f.Writer, a...)
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math/rand"
	"os"
	"time"
)

const (
	mod    int64 = 1e9 + 9
	maxn   int   = 1e5 + 5
	poolSz int   = 8e6
)

var bpow [maxn]int64

// Treap begin

const empty = 0

var (
	ptr      = 1
	usedCntr = 1
	p        [poolSz]struct {
		val, hash  int
		prio       int
		lt, rt, sz int
		used       int
	}
)

func newTreapNode(val int) int {
	for p[ptr].used == usedCntr {
		ptr++
	}
	p[ptr].val = val
	p[ptr].hash = val
	p[ptr].prio = rand.Int()
	p[ptr].sz = 1
	p[ptr].lt = empty
	p[ptr].rt = empty
	ptr++
	return ptr - 1
}

func copyNode(i int) int {
	for p[ptr].used == usedCntr {
		ptr++
	}
	p[ptr] = p[i]
	ptr++
	return ptr - 1
}

func update(i int) {
	if i == empty {
		return
	}
	lsz := p[p[i].lt].sz
	p[i].sz = lsz + 1 + p[p[i].rt].sz
	p[i].hash =
		int((int64(p[p[i].lt].hash) +
			int64(p[i].val)*bpow[lsz] +
			int64(p[p[i].rt].hash)*bpow[lsz+1]) % mod)
}

func merge(lt, rt int) (i int) {
	if lt == empty {
		return rt
	}
	if rt == empty {
		return lt
	}
	if p[lt].prio > p[rt].prio {
		i = copyNode(lt)
		p[i].rt = merge(p[i].rt, rt)
	} else {
		i = copyNode(rt)
		p[i].lt = merge(lt, p[i].lt)
	}
	update(i)
	return
}

func split(i, pos int) (lt, rt int) {
	if i == empty {
		return empty, empty
	}
	if pos == 0 {
		return empty, i
	}
	if pos >= p[i].sz {
		return i, empty
	}
	lsz := p[p[i].lt].sz
	i = copyNode(i)
	if pos <= lsz {
		lt, p[i].lt = split(p[i].lt, pos)
		rt = i
	} else {
		p[i].rt, rt = split(p[i].rt, pos-lsz-1)
		lt = i
	}
	update(i)
	return
}

func prefixHash(i, r int) int64 {
	if i == empty {
		return 0
	}
	if r >= p[i].sz {
		return int64(p[i].hash)
	}
	res := prefixHash(p[i].lt, r)
	lsz := p[p[i].lt].sz
	if r > lsz {
		res = (res + int64(p[i].val)*bpow[lsz] +
			prefixHash(p[i].rt, r-lsz-1)*bpow[lsz+1]) % mod
	}
	return res
}

func almostFull() bool {
	return ptr+maxn/100 > poolSz
}

func reset() {
	usedCntr++
	ptr = 1
}

func markUsed(i int) {
	if i == empty || p[i].used == usedCntr {
		return
	}
	p[i].used = usedCntr
	markUsed(p[i].lt)
	markUsed(p[i].rt)
}

// Treap end

// SegTree begin

type node struct {
	lt, rt int
	bad    bool
}

var defaultNode = newNode(empty, empty, false)

func newNode(lt, rt int, bad bool) *node {
	return &node{lt, rt, bad}
}

func mergeNodes(lt, rt *node) *node {
	if lt.bad || rt.bad {
		return newNode(empty, empty, true)
	}
	lrsz, rlsz := p[lt.rt].sz, p[rt.lt].sz
	mn := rlsz
	if lrsz < rlsz {
		mn = lrsz
	}
	lrhash := prefixHash(lt.rt, mn)
	rlhash := prefixHash(rt.lt, mn)
	if lrhash != rlhash {
		return newNode(empty, empty, true)
	}
	new := newNode(lt.lt, rt.rt, false)
	if mn == lrsz {
		_, nlr := split(rt.lt, mn)
		new.lt = merge(new.lt, nlr)
	} else {
		_, nrl := split(lt.rt, mn)
		new.rt = merge(new.rt, nrl)
	}
	return new
}

type segTree struct {
	n    int
	tree []*node
}

func newSegTree(n int) *segTree {
	t := &segTree{}
	t.n = 1
	for t.n < n {
		t.n *= 2
	}
	t.tree = make([]*node, t.n*2)
	for i := range t.tree {
		t.tree[i] = defaultNode
	}
	return t
}

func (t *segTree) maybeFree() {
	if almostFull() {
		reset()
		for _, n := range t.tree[1:] {
			markUsed(n.lt)
			markUsed(n.rt)
		}
	}
}

func (t *segTree) update(i, v int) {
	t.maybeFree()
	if v > 0 {
		t.tree[i+t.n] = newNode(empty, newTreapNode(v), false)
	} else {
		t.tree[i+t.n] = newNode(newTreapNode(-v), empty, false)
	}
	for i = (i + t.n) / 2; i > 0; i /= 2 {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
}

func (t *segTree) query(i, j int) bool {
	t.maybeFree()
	lt, rt := defaultNode, defaultNode
	for i, j := i+t.n, j+t.n; i <= j; i, j = (i+1)/2, (j-1)/2 {
		if i%2 == 1 {
			lt = mergeNodes(lt, t.tree[i])
		}
		if j%2 == 0 {
			rt = mergeNodes(t.tree[j], rt)
		}
	}
	res := mergeNodes(lt, rt)
	return !res.bad && p[res.lt].sz == 0 && p[res.rt].sz == 0
}

// SegTree end

func init() {
	rand.Seed(time.Now().Unix())
	base := int64(rand.Intn(int(mod)-maxn) + maxn)
	bpow[0] = 1
	for i := 1; i < maxn; i++ {
		bpow[i] = bpow[i-1] * base % mod
	}
}

func main() {
	io := newFastIO(os.Stdin, os.Stdout)
	defer io.Flush()

	n, _ := io.nextInt(), io.nextInt()
	a := io.nextInts(n)

	st := newSegTree(n)
	for i := 0; i < n; i++ {
		st.update(i, a[i])
	}

	q := io.nextInt()
	for ; q > 0; q-- {
		typ := io.nextInt()
		if typ == 1 {
			i, t := io.nextInt()-1, io.nextInt()
			st.update(i, t)
		} else {
			l, r := io.nextInt()-1, io.nextInt()-1
			if st.query(l, r) {
				io.println("Yes")
			} else {
				io.println("No")
			}
		}
	}
}

type fastIO struct {
	*bufio.Reader
	*bufio.Writer
	p [1]byte
}

func newFastIO(r io.Reader, w io.Writer) *fastIO {
	return &fastIO{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)}
}

func (f *fastIO) nextInt() int {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	neg := false
	if f.p[0] == '-' {
		neg = true
		f.Read(f.p[:])
	}
	n := 0
	for '0' <= f.p[0] && f.p[0] <= '9' {
		n = n*10 + int(f.p[0]) - '0'
		f.Read(f.p[:])
	}
	if neg {
		return -n
	}
	return n
}

func (f *fastIO) nextInts(n int) []int {
	a := make([]int, n)
	for i := 0; i < n; i++ {
		a[i] = f.nextInt()
	}
	return a
}

func (f *fastIO) next() string {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	var s []byte
	for f.p[0] > ' ' {
		s = append(s, f.p[0])
		f.Read(f.p[:])
	}
	return string(s)
}

func (f *fastIO) println(a ...interface{}) {
	fmt.Fprintln(f.Writer, a...)
}

func (f *fastIO) print(a ...interface{}) {
	fmt.Fprint(f.Writer, a...)
}

func (f *fastIO) printInts(a ...int) {
	if len(a) > 0 {
		f.print(a[0])
		for _, x := range a[1:] {
			f.print(" ", x)
		}
	}
}

func (f *fastIO) printlnInts(a ...int) {
	f.printInts(a...)
	f.println()
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"math/rand"
	"os"
	"time"
)

const (
	mod    int64 = 1e9 + 9
	maxn   int   = 1e5 + 5
	poolSz int   = 9e6
)

var bpow [maxn]int64

// Treap begin

type trNode struct {
	val, hash  int
	prio       int
	lt, rt, sz int
}

const empty = 0

var (
	ptr = 0
	p   [poolSz]trNode
	st  [100]int
)

func newTreapNode(val int) int {
	ptr++
	p[ptr] = trNode{val, val, rand.Int(), empty, empty, 1}
	return ptr
}

func copyNode(i int) int {
	ptr++
	p[ptr] = p[i]
	return ptr
}

func update(i int) {
	if i == empty {
		return
	}
	lsz := p[p[i].lt].sz
	p[i].sz = lsz + 1 + p[p[i].rt].sz
	p[i].hash =
		int((int64(p[p[i].lt].hash) +
			int64(p[i].val)*bpow[lsz] +
			int64(p[p[i].rt].hash)*bpow[lsz+1]) % mod)
}

func merge(lt, rt int) (i int) {
	ii := &i
	ptr := len(st)
	for lt != empty && rt != empty {
		if p[lt].prio > p[rt].prio {
			*ii = copyNode(lt)
			ptr--
			st[ptr] = *ii
			ii = &p[*ii].rt
			lt = p[*ii].rt
		} else {
			*ii = copyNode(rt)
			ptr--
			st[ptr] = *ii
			ii = &p[*ii].lt
			rt = p[*ii].lt
		}
	}
	if lt == empty {
		*ii = rt
	} else {
		*ii = lt
	}
	for _, n := range st[ptr:] {
		update(n)
	}
	return
}

func split(i, pos int) (lt, rt int) {
	l, r := &lt, &rt
	ptr := len(st)
	for i != empty && 0 < pos && pos < p[i].sz {
		i = copyNode(i)
		ptr--
		st[ptr] = i
		lsz := p[p[i].lt].sz
		if pos <= lsz {
			*r = i
			i, r = p[i].lt, &p[i].lt
		} else {
			*l = i
			i, l = p[i].rt, &p[i].rt
			pos -= lsz + 1
		}
	}
	if i == empty {
		*l, *r = empty, empty
	} else if pos <= 0 {
		*l, *r = empty, i
	} else if pos >= p[i].sz {
		*l, *r = i, empty
	}
	for _, n := range st[ptr:] {
		update(n)
	}
	return
}

func prefixHash(i, r int) int64 {
	if i == empty {
		return 0
	}
	if r >= p[i].sz {
		return int64(p[i].hash)
	}
	res := prefixHash(p[i].lt, r)
	lsz := p[p[i].lt].sz
	if r > lsz {
		res = (res + int64(p[i].val)*bpow[lsz] +
			prefixHash(p[i].rt, r-lsz-1)*bpow[lsz+1]) % mod
	}
	return res
}

// Treap end

// SegTree begin

type node struct {
	lt, rt int
	bad    bool
}

var defaultNode = newNode(empty, empty, false)
var badNode = newNode(empty, empty, true)

func newNode(lt, rt int, bad bool) *node {
	return &node{lt, rt, bad}
}

func mergeNodes(lt, rt *node) *node {
	if lt.bad || rt.bad {
		return badNode
	}
	lrsz, rlsz := p[lt.rt].sz, p[rt.lt].sz
	mn := rlsz
	if lrsz < rlsz {
		mn = lrsz
	}
	lrhash := prefixHash(lt.rt, mn)
	rlhash := prefixHash(rt.lt, mn)
	if lrhash != rlhash {
		return badNode
	}
	new := newNode(lt.lt, rt.rt, false)
	if mn == lrsz {
		_, nlr := split(rt.lt, mn)
		new.lt = merge(new.lt, nlr)
	} else {
		_, nrl := split(lt.rt, mn)
		new.rt = merge(new.rt, nrl)
	}
	return new
}

type segTree struct {
	n    int
	tree []*node
}

func nodeForVal(v int) *node {
	if v > 0 {
		return newNode(empty, newTreapNode(v), false)
	}
	return newNode(newTreapNode(-v), empty, false)
}

func newSegTree(a []int) *segTree {
	t := &segTree{}
	t.n = 1
	for t.n < len(a) {
		t.n *= 2
	}
	t.tree = make([]*node, t.n*2)
	for i, v := range a {
		t.tree[i+t.n] = nodeForVal(v)
	}
	for i := len(a); i < t.n; i++ {
		t.tree[i+t.n] = defaultNode
	}
	for i := t.n - 1; i > 0; i-- {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
	return t
}

func (t *segTree) update(i, v int) {
	t.tree[i+t.n] = nodeForVal(v)
	for i = (i + t.n) / 2; i > 0; i /= 2 {
		t.tree[i] = mergeNodes(t.tree[i*2], t.tree[i*2+1])
	}
}

func (t *segTree) query(i, j int) bool {
	lt, rt := defaultNode, defaultNode
	for i, j := i+t.n, j+t.n; i <= j; i, j = (i+1)/2, (j-1)/2 {
		if i%2 == 1 {
			lt = mergeNodes(lt, t.tree[i])
		}
		if j%2 == 0 {
			rt = mergeNodes(t.tree[j], rt)
		}
	}
	res := mergeNodes(lt, rt)
	return !res.bad && p[res.lt].sz == 0 && p[res.rt].sz == 0
}

// SegTree end

func init() {
	rand.Seed(time.Now().Unix())
	base := int64(rand.Intn(int(mod)-maxn) + maxn)
	bpow[0] = 1
	for i := 1; i < maxn; i++ {
		bpow[i] = bpow[i-1] * base % mod
	}
}

// Taking some cues from ecnerwala
// https://codeforces.com/contest/1340/submission/77861280

func main() {
	io := newFastIO(os.Stdin, os.Stdout)
	defer io.Flush()

	n, _ := io.nextInt(), io.nextInt()
	a := io.nextInts(n)

	ptrInitial := ptr
	st := newSegTree(a)

	for q := io.nextInt(); q > 0; q-- {
		if ptr+400 >= poolSz {
			ptr = ptrInitial
			st = newSegTree(a)
		}
		typ := io.nextInt()
		if typ == 1 {
			i, t := io.nextInt()-1, io.nextInt()
			a[i] = t
			st.update(i, t)
		} else {
			oldPtr := ptr
			l, r := io.nextInt()-1, io.nextInt()-1
			if st.query(l, r) {
				io.println("Yes")
			} else {
				io.println("No")
			}
			ptr = oldPtr
		}
	}
}

type fastIO struct {
	*bufio.Reader
	*bufio.Writer
	p [1]byte
}

func newFastIO(r io.Reader, w io.Writer) *fastIO {
	return &fastIO{Reader: bufio.NewReader(r), Writer: bufio.NewWriter(w)}
}

func (f *fastIO) nextInt() int {
	f.Read(f.p[:])
	for f.p[0] <= ' ' {
		f.Read(f.p[:])
	}
	neg := false
	if f.p[0] == '-' {
		neg = true
		f.Read(f.p[:])
	}
	n := 0
	for '0' <= f.p[0] && f.p[0] <= '9' {
		n = n*10 + int(f.p[0]) - '0'
		f.Read(f.p[:])
	}
	if neg {
		return -n
	}
	return n
}

func (f *fastIO) nextInts(n int) []int {
	a := make([]int, n)
	for i := 0; i < n; i++ {
		a[i] = f.nextInt()
	}
	return a
}

func (f *fastIO) println(a ...interface{}) {
	fmt.Fprintln(f.Writer, a...)
}


package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	s, _ := reader.ReadString('\n')
	a, _ := reader.ReadString('\n')
	b, _ := reader.ReadString('\n')

	ans := solve(normalize(s), normalize(a), normalize(b))

	fmt.Println(ans)
}

func normalize(s string) string {

	for i := len(s); i > 0; i-- {
		if s[i-1] >= 'a' && s[i-1] <= 'z' {
			return s[:i]
		}
	}
	return ""
}

func solve(s string, a string, b string) string {
	res1 := check(s, a, b)
	res2 := check(reverse(s), a, b)

	if res1 {
		if res2 {
			return "both"
		}
		return "forward"
	}

	if res2 {
		return "backward"
	}
	return "fantasy"
}

func check(s string, a string, b string) bool {
	x := getLps(a)
	y := getLps(b)

	i := find(s, a, x)
	if i >= 0 {
		j := i + len(a)

		if find(s[j:], b, y) >= 0 {
			return true
		}
	}
	return false
}

func find(s string, pat string, lps []int) int {
	for i, j := 0, 0; i < len(s); {
		if s[i] == pat[j] {
			i++
			j++
		}
		if j == len(pat) {
			return i - len(pat)
		}
		if i < len(s) && s[i] != pat[j] {
			if j > 0 {
				j = lps[j-1]
			} else {
				i++
			}
		}
	}

	return -1
}

func getLps(pat string) []int {
	m := len(pat)
	lps := make([]int, m)
	for l, i := 0, 1; i < m; {
		if pat[l] == pat[i] {
			l++
			lps[i] = l
			i++
		} else {
			if l > 0 {
				l = lps[l-1]
			} else {
				lps[i] = 0
				i++
			}
		}
	}
	return lps
}

func reverse(s string) string {
	buf := []byte(s)

	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
		buf[i], buf[j] = buf[j], buf[i]
	}

	return string(buf)
}

// https://codeforces.com/contest/8/problem/A
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
	"bytes"
)

// (c) Dmitriy Blokhin (sv.dblokhin@gmail.com)

func main() {
	//f, _ := os.Open("input.txt")
	//input := bufio.NewReader(f)
	input := bufio.NewReader(os.Stdin)
	var path, a, b string
	fmt.Fscanf(input, "%s\n", &path)
	fmt.Fscanf(input, "%s\n", &a)
	fmt.Fscanf(input, "%s\n", &b)
	var buffer bytes.Buffer
	for i := len(path) - 1; i >= 0; i-- {
		buffer.WriteByte(path[i])
	}
	rpath := buffer.String()
	la := strings.Index(path, a)
	ra := strings.Index(rpath, a)
	forward := la > -1 && la + len(a) - 1 < strings.LastIndex(path, b)
	backward := ra > -1 && ra + len(a) - 1 < strings.LastIndex(rpath, b)
	if forward && backward {
		fmt.Println("both")
	} else if !forward && !backward {
		fmt.Println("fantasy")
	} else if forward {
		fmt.Println("forward")
	} else  {
		fmt.Println("backward")
	}
}

package main

import (
	"strings"
	"fmt"
	"strconv"
	"errors"
	"io"
	"unicode/utf8"
	"bytes"
	"os"
)

func main() {
	s, a, b := nextWord(), nextWord(), nextWord()
	ss_ := make([]rune, len(s))
	for i, x := range []rune(s) {
		ss_[len(ss_) - 1 - i] = x
	}
	ss := string(ss_)
	fa, fb := strings.Index(s, a), strings.LastIndex(s, b)
	fwd :=  fa != -1 && fb != -1 && fb >= fa + len(a)
	ba, bb := strings.Index(ss, a), strings.LastIndex(ss, b)
	bwd :=  ba != -1 && bb != -1 && bb >= ba + len(a)

	switch {
	case fwd && bwd:
		printf("both")
	case fwd:
		printf("forward")
	case bwd:
		printf("backward")
	default:
		printf("fantasy")
	}
	printf("\n")
}

var lineScanner *Scanner
var wordScanner *Scanner

func init() {
	lineScanner = NewScanner(os.Stdin)
	wordScanner = NewScanner(strings.NewReader(""))
	wordScanner.Split(ScanWords)
}

func printf(format string, a ...interface{}) {
	fmt.Printf(format, a...)
}
func nextLine() (string, error) {
	if !lineScanner.Scan() {
		if err := lineScanner.Err(); err != nil {
			panic(err)
		}
		return "", errors.New("nextLine: EOF reached")
	}
	return lineScanner.Text(), nil
}

func nextWord() string {
	for !wordScanner.Scan() {
		if err := wordScanner.Err(); err != nil {
			panic(err)
		}
		line, err := nextLine()
		if err != nil {
			return ""
		}
		wordScanner = NewScanner(strings.NewReader(line))
		wordScanner.Split(ScanWords)
	}
	return wordScanner.Text()
}

func nextInt() int {
	res, err := strconv.Atoi(nextWord())
	if err != nil {
		panic(err)
	}
	return res
}

func nextInt64() int64 {
	res, err := strconv.ParseInt(nextWord(), 10, 64)
	if err != nil {
		panic(err)
	}
	return res
}

func nextFloat64() float64 {
	res, err := strconv.ParseFloat(nextWord(), 64)
	if err != nil {
		panic(err)
	}
	return res
}

// Scanner provides a convenient interface for reading data such as
// a file of newline-delimited lines of text. Successive calls to
// the Scan method will step through the 'tokens' of a file, skipping
// the bytes between the tokens. The specification of a token is
// defined by a split function of type SplitFunc; the default split
// function breaks the input into lines with line termination stripped. Split
// functions are defined in this package for scanning a file into
// lines, bytes, UTF-8-encoded runes, and space-delimited words. The
// client may instead provide a custom split function.
//
// Scanning stops unrecoverably at EOF, the first I/O error, or a token too
// large to fit in the buffer. When a scan stops, the reader may have
// advanced arbitrarily far past the last token. Programs that need more
// control over error handling or large tokens, or must run sequential scans
// on a reader, should use bufio.Reader instead.
//
type Scanner struct {
	r            io.Reader // The reader provided by the client.
	split        SplitFunc // The function to split the tokens.
	maxTokenSize int       // Maximum size of a token; modified by tests.
	token        []byte    // Last token returned by split.
	buf          []byte    // Buffer used as argument to split.
	start        int       // First non-processed byte in buf.
	end          int       // End of data in buf.
	err          error     // Sticky error.
	empties      int       // Count of successive empty tokens.
	scanCalled   bool      // Scan has been called; buffer is in use.
	done         bool      // Scan has finished.
}

// SplitFunc is the signature of the split function used to tokenize the
// input. The arguments are an initial substring of the remaining unprocessed
// data and a flag, atEOF, that reports whether the Reader has no more data
// to give. The return values are the number of bytes to advance the input
// and the next token to return to the user, plus an error, if any. If the
// data does not yet hold a complete token, for instance if it has no newline
// while scanning lines, SplitFunc can return (0, nil, nil) to signal the
// Scanner to read more data into the slice and try again with a longer slice
// starting at the same point in the input.
//
// If the returned error is non-nil, scanning stops and the error
// is returned to the client.
//
// The function is never called with an empty data slice unless atEOF
// is true. If atEOF is true, however, data may be non-empty and,
// as always, holds unprocessed text.
type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)

// Errors returned by Scanner.
var (
	ErrTooLong = errors.New("bufio.Scanner: token too long")
	ErrNegativeAdvance = errors.New("bufio.Scanner: SplitFunc returns negative advance count")
	ErrAdvanceTooFar = errors.New("bufio.Scanner: SplitFunc returns advance count beyond input")
)

const (
	// MaxScanTokenSize is the maximum size used to buffer a token
	// unless the user provides an explicit buffer with Scan.Buffer.
	// The actual maximum token size may be smaller as the buffer
	// may need to include, for instance, a newline.
	MaxScanTokenSize = 2 * 1024 * 2014

	startBufSize = 4096 // Size of initial allocation for buffer.
)

// NewScanner returns a new Scanner to read from r.
// The split function defaults to ScanLines.
func NewScanner(r io.Reader) *Scanner {
	return &Scanner{
		r:            r,
		split:        ScanLines,
		maxTokenSize: MaxScanTokenSize,
	}
}

// Err returns the first non-EOF error that was encountered by the Scanner.
func (s *Scanner) Err() error {
	if s.err == io.EOF {
		return nil
	}
	return s.err
}

// Bytes returns the most recent token generated by a call to Scan.
// The underlying array may point to data that will be overwritten
// by a subsequent call to Scan. It does no allocation.
func (s *Scanner) Bytes() []byte {
	return s.token
}

// Text returns the most recent token generated by a call to Scan
// as a newly allocated string holding its bytes.
func (s *Scanner) Text() string {
	return string(s.token)
}

// ErrFinalToken is a special sentinel error value. It is intended to be
// returned by a Split function to indicate that the token being delivered
// with the error is the last token and scanning should stop after this one.
// After ErrFinalToken is received by Scan, scanning stops with no error.
// The value is useful to stop processing early or when it is necessary to
// deliver a final empty token. One could achieve the same behavior
// with a custom error value but providing one here is tidier.
// See the emptyFinalToken example for a use of this value.
var ErrFinalToken = errors.New("final token")

// Scan advances the Scanner to the next token, which will then be
// available through the Bytes or Text method. It returns false when the
// scan stops, either by reaching the end of the input or an error.
// After Scan returns false, the Err method will return any error that
// occurred during scanning, except that if it was io.EOF, Err
// will return nil.
// Scan panics if the split function returns 100 empty tokens without
// advancing the input. This is a common error mode for scanners.
func (s *Scanner) Scan() bool {
	if s.done {
		return false
	}
	s.scanCalled = true
	// Loop until we have a token.
	for {
		// See if we can get a token with what we already have.
		// If we've run out of data but have an error, give the split function
		// a chance to recover any remaining, possibly empty token.
		if s.end > s.start || s.err != nil {
			advance, token, err := s.split(s.buf[s.start:s.end], s.err != nil)
			if err != nil {
				if err == ErrFinalToken {
					s.token = token
					s.done = true
					return true
				}
				s.setErr(err)
				return false
			}
			if !s.advance(advance) {
				return false
			}
			s.token = token
			if token != nil {
				if s.err == nil || advance > 0 {
					s.empties = 0
				} else {
					// Returning tokens not advancing input at EOF.
					s.empties++
					if s.empties > 100 {
						panic("bufio.Scan: 100 empty tokens without progressing")
					}
				}
				return true
			}
		}
		// We cannot generate a token with what we are holding.
		// If we've already hit EOF or an I/O error, we are done.
		if s.err != nil {
			// Shut it down.
			s.start = 0
			s.end = 0
			return false
		}
		// Must read more data.
		// First, shift data to beginning of buffer if there's lots of empty space
		// or space is needed.
		if s.start > 0 && (s.end == len(s.buf) || s.start > len(s.buf) / 2) {
			copy(s.buf, s.buf[s.start:s.end])
			s.end -= s.start
			s.start = 0
		}
		// Is the buffer full? If so, resize.
		if s.end == len(s.buf) {
			// Guarantee no overflow in the multiplication below.
			const maxInt = int(^uint(0) >> 1)
			if len(s.buf) >= s.maxTokenSize || len(s.buf) > maxInt / 2 {
				s.setErr(ErrTooLong)
				return false
			}
			newSize := len(s.buf) * 2
			if newSize == 0 {
				newSize = startBufSize
			}
			if newSize > s.maxTokenSize {
				newSize = s.maxTokenSize
			}
			newBuf := make([]byte, newSize)
			copy(newBuf, s.buf[s.start:s.end])
			s.buf = newBuf
			s.end -= s.start
			s.start = 0
			continue
		}
		// Finally we can read some input. Make sure we don't get stuck with
		// a misbehaving Reader. Officially we don't need to do this, but let's
		// be extra careful: Scanner is for safe, simple jobs.
		for loop := 0;; {
			n, err := s.r.Read(s.buf[s.end:len(s.buf)])
			s.end += n
			if err != nil {
				s.setErr(err)
				break
			}
			if n > 0 {
				s.empties = 0
				break
			}
			loop++
			if loop > 10 {
				s.setErr(io.ErrNoProgress)
				break
			}
		}
	}
}

// advance consumes n bytes of the buffer. It reports whether the advance was legal.
func (s *Scanner) advance(n int) bool {
	if n < 0 {
		s.setErr(ErrNegativeAdvance)
		return false
	}
	if n > s.end - s.start {
		s.setErr(ErrAdvanceTooFar)
		return false
	}
	s.start += n
	return true
}

// setErr records the first error encountered.
func (s *Scanner) setErr(err error) {
	if s.err == nil || s.err == io.EOF {
		s.err = err
	}
}

// Buffer sets the initial buffer to use when scanning and the maximum
// size of buffer that may be allocated during scanning. The maximum
// token size is the larger of max and cap(buf). If max <= cap(buf),
// Scan will use this buffer only and do no allocation.
//
// By default, Scan uses an internal buffer and sets the
// maximum token size to MaxScanTokenSize.
//
// Buffer panics if it is called after scanning has started.
func (s *Scanner) Buffer(buf []byte, max int) {
	if s.scanCalled {
		panic("Buffer called after Scan")
	}
	s.buf = buf[0:cap(buf)]
	s.maxTokenSize = max
}

// Split sets the split function for the Scanner.
// The default split function is ScanLines.
//
// Split panics if it is called after scanning has started.
func (s *Scanner) Split(split SplitFunc) {
	if s.scanCalled {
		panic("Split called after Scan")
	}
	s.split = split
}

// Split functions

// ScanBytes is a split function for a Scanner that returns each byte as a token.
func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error) {
	if atEOF && len(data) == 0 {
		return 0, nil, nil
	}
	return 1, data[0:1], nil
}

var errorRune = []byte(string(utf8.RuneError))

// ScanRunes is a split function for a Scanner that returns each
// UTF-8-encoded rune as a token. The sequence of runes returned is
// equivalent to that from a range loop over the input as a string, which
// means that erroneous UTF-8 encodings translate to U+FFFD = "\xef\xbf\xbd".
// Because of the Scan interface, this makes it impossible for the client to
// distinguish correctly encoded replacement runes from encoding errors.
func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error) {
	if atEOF && len(data) == 0 {
		return 0, nil, nil
	}

	// Fast path 1: ASCII.
	if data[0] < utf8.RuneSelf {
		return 1, data[0:1], nil
	}

	// Fast path 2: Correct UTF-8 decode without error.
	_, width := utf8.DecodeRune(data)
	if width > 1 {
		// It's a valid encoding. Width cannot be one for a correctly encoded
		// non-ASCII rune.
		return width, data[0:width], nil
	}

	// We know it's an error: we have width==1 and implicitly r==utf8.RuneError.
	// Is the error because there wasn't a full rune to be decoded?
	// FullRune distinguishes correctly between erroneous and incomplete encodings.
	if !atEOF && !utf8.FullRune(data) {
		// Incomplete; get more bytes.
		return 0, nil, nil
	}

	// We have a real UTF-8 encoding error. Return a properly encoded error rune
	// but advance only one byte. This matches the behavior of a range loop over
	// an incorrectly encoded string.
	return 1, errorRune, nil
}

// dropCR drops a terminal \r from the data.
func dropCR(data []byte) []byte {
	if len(data) > 0 && data[len(data) - 1] == '\r' {
		return data[0 : len(data) - 1]
	}
	return data
}

// ScanLines is a split function for a Scanner that returns each line of
// text, stripped of any trailing end-of-line marker. The returned line may
// be empty. The end-of-line marker is one optional carriage return followed
// by one mandatory newline. In regular expression notation, it is `\r?\n`.
// The last non-empty line of input will be returned even if it has no
// newline.
func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
	if atEOF && len(data) == 0 {
		return 0, nil, nil
	}
	if i := bytes.IndexByte(data, '\n'); i >= 0 {
		// We have a full newline-terminated line.
		return i + 1, dropCR(data[0:i]), nil
	}
	// If we're at EOF, we have a final, non-terminated line. Return it.
	if atEOF {
		return len(data), dropCR(data), nil
	}
	// Request more data.
	return 0, nil, nil
}

// isSpace reports whether the character is a Unicode white space character.
// We avoid dependency on the unicode package, but check validity of the implementation
// in the tests.
func isSpace(r rune) bool {
	if r <= '\u00FF' {
		// Obvious ASCII ones: \t through \r plus space. Plus two Latin-1 oddballs.
		switch r {
		case ' ', '\t', '\n', '\v', '\f', '\r':
			return true
		case '\u0085', '\u00A0':
			return true
		}
		return false
	}
	// High-valued ones.
	if '\u2000' <= r && r <= '\u200a' {
		return true
	}
	switch r {
	case '\u1680', '\u2028', '\u2029', '\u202f', '\u205f', '\u3000':
		return true
	}
	return false
}

// ScanWords is a split function for a Scanner that returns each
// space-separated word of text, with surrounding spaces deleted. It will
// never return an empty string. The definition of space is set by
// unicode.IsSpace.
func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error) {
	// Skip leading spaces.
	start := 0
	for width := 0; start < len(data); start += width {
		var r rune
		r, width = utf8.DecodeRune(data[start:])
		if !isSpace(r) {
			break
		}
	}
	// Scan until space, marking end of word.
	for width, i := 0, start; i < len(data); i += width {
		var r rune
		r, width = utf8.DecodeRune(data[i:])
		if isSpace(r) {
			return i + width, data[start:i], nil
		}
	}
	// If we're at EOF, we have a final, non-empty, non-terminated word. Return it.
	if atEOF && len(data) > start {
		return len(data), data[start:], nil
	}
	// Request more data.
	return start, nil, nil
}

// Author: sighduck
// URL: https://codeforces.com/contest/8/problem/A

package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func isValidOrder(flags string, firstPeriod string, secondPeriod string) bool {
	firstPeriodForwardIndex := strings.Index(flags, firstPeriod)
	if firstPeriodForwardIndex == -1 {
		return false
	}
	secondPeriodForwardIndex := strings.Index(
		flags[firstPeriodForwardIndex+len(firstPeriod):],
		secondPeriod,
	)
	if secondPeriodForwardIndex == -1 {
		return false
	}
	return true
}

func reverse(s string) string {
	runes := []rune(s)
	for i := 0; i < len(s)/2; i++ {
		runes[i], runes[len(s)-1-i] = runes[len(s)-1-i], runes[i]
	}
	return string(runes)
}

func Solve(flags string, firstPeriod string, secondPeriod string) string {
	isValidForward := isValidOrder(flags, firstPeriod, secondPeriod)
	isValidBackward := isValidOrder(reverse(flags), firstPeriod, secondPeriod)
	if isValidForward && isValidBackward {
		return "both"
	} else if isValidForward {
		return "forward"
	} else if isValidBackward {
		return "backward"
	}
	return "fantasy"
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	var flags string
	var firstPeriod string
	var secondPeriod string
	fmt.Fscanf(reader, "%s\n", &flags)
	fmt.Fscanf(reader, "%s\n", &firstPeriod)
	fmt.Fscanf(reader, "%s\n", &secondPeriod)
	fmt.Fprintf(writer, "%s\n", Solve(flags, firstPeriod, secondPeriod))
}

package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"strings"
)

func reverse(s string) string {
	b := []byte(s)
	for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
		b[i], b[j] = b[j], b[i]
	}
	return string(b)
}

func main() {
	bs, _ := ioutil.ReadAll(os.Stdin)
	reader := bytes.NewBuffer(bs)

	var s, s0, s1 string
	var forward, backward bool

	fmt.Fscanf(reader, "%s\n", &s)
	fmt.Fscanf(reader, "%s\n", &s0)
	fmt.Fscanf(reader, "%s", &s1)

	findex0 := strings.Index(s, s0)
	findex1 := strings.LastIndex(s, s1)
	if findex0 == -1 || findex1 == -1 || findex1-findex0 < len(s0) {
		forward = false
	} else {
		forward = true
	}

	s = reverse(s)
	bindex0 := strings.Index(s, s0)
	bindex1 := strings.LastIndex(s, s1)
	if bindex0 == -1 || bindex1 == -1 || bindex1-bindex0 < len(s0) {
		backward = false
	} else {
		backward = true
	}

	if forward && backward {
		fmt.Printf("both\n")
	} else if forward && !backward {
		fmt.Printf("forward\n")
	} else if !forward && backward {
		fmt.Printf("backward\n")
	} else {
		fmt.Printf("fantasy")
	}
}

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func solve() {
	s := readString()
	sr := Reverse(s)

	s1 := readString()
	s2 := readString()

	forward := try_it(s, s1, s2)
	backward := try_it(sr, s1, s2)

	if forward && backward {
		fmt.Println("both")
	} else if forward {
		fmt.Println("forward")
	} else if backward {
		fmt.Println("backward")
	} else {
		fmt.Println("fantasy")
	}
}

func try_it(s, s1, s2 string) bool {
	i := strings.Index(s, s1)
	if i == -1 {
		return false
	}

	i = strings.Index(s[i+len(s1):], s2)
	if i == -1 {
		return false
	}

	return true
}

func Reverse(s string) string {
	runes := []rune(s)
	for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 {
		runes[i], runes[j] = runes[j], runes[i]
	}
	return string(runes)
}

var scanner *bufio.Scanner

func main() {
	scanner = bufio.NewScanner(os.Stdin)
	const MaxTokenLength = 1024 * 1024
	scanner.Buffer(make([]byte, 0, MaxTokenLength), MaxTokenLength)
	scanner.Split(bufio.ScanWords)
	solve()
}

func readString() string {
	scanner.Scan()
	return scanner.Text()
}

func readInt() int {
	val, _ := strconv.Atoi(readString())
	return val
}

func readInt64() int64 {
	v, _ := strconv.ParseInt(readString(), 10, 64)
	return v
}

package main

import (
  "os"
  "bufio"
  "strings"
  "strconv"
  "fmt"
)

var scanner *bufio.Scanner

func getI64() int64 {
  scanner.Scan()
  x, _ := strconv.ParseInt(scanner.Text(), 10, 64)
  return x
}
func getI() int {
  return int(getI64())
}
func getF() float64 {
  scanner.Scan()
  x, _ := strconv.ParseFloat(scanner.Text(), 64)
  return x
}
func getS() string {
  scanner.Scan()
  return scanner.Text()
}

func seek(s, a, b string) bool {
  aPos := strings.Index(s, a)
  if aPos != -1 {
    bPos := strings.Index(s[aPos+len(a):], b)
    if bPos != -1 {
      return true
    }
  }
  return false
}

func main() {
  reader := bufio.NewReader(os.Stdin)
  writer := bufio.NewWriter(os.Stdout)
  defer writer.Flush()

  line, _ := reader.ReadString('\n')
  ab := strings.TrimSpace(line)
  n := len(ab)
  baBytes := make([]byte, n)
  for i := 0; i < n; i++ {
    baBytes[i] = ab[n-1-i]
  }
  ba := string(baBytes)
  line, _ = reader.ReadString('\n')
  s1 := strings.TrimSpace(line)
  line, _ = reader.ReadString('\n')
  s2 := strings.TrimSpace(line)
  forward, backward := seek(ab, s1, s2), seek(ba, s1, s2)
  result := "fantasy"
  if forward && backward {
    result = "both"
  } else if forward {
    result = "forward"
  } else if backward {
    result = "backward"
  }
  writer.WriteString(fmt.Sprintf("%s\n", result))
}

package main

import (
  "os"
  "bufio"
  "strings"
  "strconv"
  "fmt"
)

var scanner *bufio.Scanner

func getI64() int64 {
  scanner.Scan()
  x, _ := strconv.ParseInt(scanner.Text(), 10, 64)
  return x
}
func getI() int {
  return int(getI64())
}
func getF() float64 {
  scanner.Scan()
  x, _ := strconv.ParseFloat(scanner.Text(), 64)
  return x
}
func getS() string {
  scanner.Scan()
  return scanner.Text()
}

func seek(s, a, b string) bool {
  aPos := strings.Index(s, a)
  if aPos != -1 {
    bPos := strings.Index(s[aPos+len(a):], b)
    if bPos != -1 {
      return true
    }
  }
  return false
}

func main() {
  scanner = bufio.NewScanner(os.Stdin)
  scanner.Split(bufio.ScanWords)
  writer := bufio.NewWriter(os.Stdout)
  defer writer.Flush()

  ab := getS()
  n := len(ab)
  baBytes := make([]byte, n)
  for i := 0; i < n; i++ {
    baBytes[i] = ab[n-1-i]
  }
  ba := string(baBytes)
  s1, s2 := getS(), getS()
  forward, backward := seek(ab, s1, s2), seek(ba, s1, s2)
  result := "fantasy"
  if forward && backward {
    result = "both"
  } else if forward {
    result = "forward"
  } else if backward {
    result = "backward"
  }
  writer.WriteString(fmt.Sprintf("%s\n", result))
}

// https://codeforces.com/contest/8/problem/A
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
	"bytes"
)

// (c) Dmitriy Blokhin (sv.dblokhin@gmail.com)

func main() {
	//f, _ := os.Open("input.txt")
	//input := bufio.NewReader(f)
	input := bufio.NewReader(os.Stdin)
	var path, a, b string
	fmt.Fscanf(input, "%s\n", &path)
	fmt.Fscanf(input, "%s\n", &a)
	fmt.Fscanf(input, "%s\n", &b)
	var buffer bytes.Buffer
	for i := len(path) - 1; i >= 0; i-- {
		buffer.WriteByte(path[i])
	}
	rpath := buffer.String()
	la := strings.Index(path, a)
	ra := strings.Index(rpath, a)
	forward := la > -1 && la + len(a) < strings.LastIndex(path, b)
	backward := ra > -1 && ra + len(a) < strings.LastIndex(rpath, b)
	if forward && backward {
		fmt.Println("both")
	} else if !forward && !backward {
		fmt.Println("fantasy")
	} else if forward {
		fmt.Println("forward")
	} else  {
		fmt.Println("backward")
	}
}

// https://codeforces.com/contest/2/problem/A
package main

import (
	"bufio"
	"fmt"
	"os"
)

// (c) Dmitriy Blokhin (sv.dblokhin@gmail.com)

func main() {
	var (
		n int
	)

	//f, _ := os.Open("input.txt")
	//input := bufio.NewReader(f)
	input := bufio.NewReader(os.Stdin)
	fmt.Fscanln(input, &n)
	total := make(map[string]int)
	histn := make([]string, n)
	hists := make([]int, n)
	for i := 0; i < n; i++ {
		var name string
		var score int
		fmt.Fscanln(input, &name, &score)
		histn[i] = name
		hists[i] = score
		total[name] += score
	}
	max := 0
	wins := make(map[string]bool)
	for name, scores := range total {
		if scores >= max {
			if scores > max {
				max = scores
				wins = make(map[string]bool)
			}
			wins[name] = true
		}
	}

	result := make(map[string]int)
	for i := 0; i < len(histn); i++ {
		name := histn[i]
		if wins[name] {
			result[name] += hists[i]
			if result[name] >= max {
				fmt.Println(name)
				return
			}
		}
	}
}

// https://codeforces.com/contest/8/problem/A
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
	"bytes"
)

// (c) Dmitriy Blokhin (sv.dblokhin@gmail.com)

func main() {
	//f, _ := os.Open("input.txt")
	//input := bufio.NewReader(f)
	input := bufio.NewReader(os.Stdin)
	var path, a, b string
	fmt.Fscanln(input, &path)
	fmt.Fscanln(input, &a)
	fmt.Fscanln(input, &b)
	var buffer bytes.Buffer
	for i := len(a) - 1; i >= 0; i-- {
		buffer.WriteByte(a[i])
	}
	reca := buffer.String()
	buffer.Reset()
	for i := len(b) - 1; i >= 0; i-- {
		buffer.WriteByte(b[i])
	}
	recb := buffer.String()
	la := strings.Index(path, a)
	forward := la > -1 && la < strings.LastIndex(path, b)
	rb := strings.Index(path, recb)
	backward := rb > -1 && rb < strings.LastIndex(path, reca)
	if forward && backward {
		fmt.Println("both")
	} else if !forward && !backward {
		fmt.Println("fantasy")
	} else if forward {
		fmt.Println("forward")
	} else  {
		fmt.Println("backward")
	}
}

// https://codeforces.com/contest/8/problem/A
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
	"bytes"
)

// (c) Dmitriy Blokhin (sv.dblokhin@gmail.com)

func main() {
	//f, _ := os.Open("input.txt")
	//input := bufio.NewReader(f)
	input := bufio.NewReader(os.Stdin)
	var path, a, b string
	fmt.Fscanln(input, &path)
	fmt.Fscanln(input, &a)
	fmt.Fscanln(input, &b)
	var buffer bytes.Buffer
	for i := len(path) - 1; i >= 0; i-- {
		buffer.WriteByte(path[i])
	}
	rpath := buffer.String()
	la := strings.Index(path, a)
	forward := la > -1 && la <= strings.LastIndex(path, b)
	ra := strings.Index(rpath, a)
	backward := ra > -1 && ra <= strings.LastIndex(rpath, b)
	if forward && backward {
		fmt.Println("both")
	} else if !forward && !backward {
		fmt.Println("fantasy")
	} else if forward {
		fmt.Println("forward")
	} else  {
		fmt.Println("backward")
	}
}

// https://codeforces.com/contest/8/problem/A
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
	"bytes"
)

// (c) Dmitriy Blokhin (sv.dblokhin@gmail.com)

func main() {
	//f, _ := os.Open("input.txt")
	//input := bufio.NewReader(f)
	input := bufio.NewReader(os.Stdin)
	var path, a, b string
	fmt.Fscanf(input, "%s\n", &path)
	fmt.Fscanf(input, "%s\n", &a)
	fmt.Fscanf(input, "%s\n", &b)
	var buffer bytes.Buffer
	for i := len(path) - 1; i >= 0; i-- {
		buffer.WriteByte(path[i])
	}
	rpath := buffer.String()
	la := strings.Index(path, a)
	forward := la > -1 && la <= strings.LastIndex(path, b)
	ra := strings.Index(rpath, a)
	backward := ra > -1 && ra <= strings.LastIndex(rpath, b)
	if forward && backward {
		fmt.Println("both")
	} else if !forward && !backward {
		fmt.Println("fantasy")
	} else if forward {
		fmt.Println("forward")
	} else  {
		fmt.Println("backward")
	}
}

// https://codeforces.com/contest/8/problem/A
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
	"bytes"
)

// (c) Dmitriy Blokhin (sv.dblokhin@gmail.com)

func main() {
	//f, _ := os.Open("input.txt")
	//input := bufio.NewReader(f)
	input := bufio.NewReader(os.Stdin)
	var path, a, b string
	fmt.Fscanln(input, &path)
	fmt.Fscanln(input, &a)
	fmt.Fscanln(input, &b)
	var buffer bytes.Buffer
	for i := len(path) - 1; i >= 0; i-- {
		buffer.WriteByte(path[i])
	}
	rpath := buffer.String()
	la := strings.Index(path, a)
	forward := la > -1 && la < strings.LastIndex(path, b)
	ra := strings.Index(rpath, a)
	backward := ra > -1 && ra < strings.LastIndex(rpath, b)
	if forward && backward {
		fmt.Println("both")
	} else if !forward && !backward {
		fmt.Println("fantasy")
	} else if forward {
		fmt.Println("forward")
	} else  {
		fmt.Println("backward")
	}
}

// https://codeforces.com/contest/8/problem/A
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
	"bytes"
)

// (c) Dmitriy Blokhin (sv.dblokhin@gmail.com)

func main() {
	//f, _ := os.Open("input.txt")
	//input := bufio.NewReader(f)
	input := bufio.NewReader(os.Stdin)
	var path, a, b string
	fmt.Fscanf(input, "%s", &path)
	fmt.Fscanf(input, "%s", &a)
	fmt.Fscanf(input, "%s", &b)
	var buffer bytes.Buffer
	for i := len(path) - 1; i >= 0; i-- {
		buffer.WriteByte(path[i])
	}
	rpath := buffer.String()
	la := strings.Index(path, a)
	forward := la > -1 && la <= strings.LastIndex(path, b)
	ra := strings.Index(rpath, a)
	backward := ra > -1 && ra <= strings.LastIndex(rpath, b)
	if forward && backward {
		fmt.Println("both")
	} else if !forward && !backward {
		fmt.Println("fantasy")
	} else if forward {
		fmt.Println("forward")
	} else  {
		fmt.Println("backward")
	}
}

// Author: sighduck
// URL: https://codeforces.com/contest/8/problem/A

package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

func isValidOrder(flags string, firstPeriod string, secondPeriod string) bool {
	firstPeriodForwardIndex := strings.Index(flags, firstPeriod)
	if firstPeriodForwardIndex == -1 {
		return false
	}
	secondPeriodForwardIndex := strings.Index(flags[firstPeriodForwardIndex:], secondPeriod)
	if secondPeriodForwardIndex == -1 {
		return false
	}
	return true
}

func reverse(s string) string {
	runes := []rune(s)
	for i := 0; i < len(s)/2; i++ {
		runes[i], runes[len(s)-1-i] = runes[len(s)-1-i], runes[i]
	}
	return string(runes)
}

func Solve(flags string, firstPeriod string, secondPeriod string) string {
	isValidForward := isValidOrder(flags, firstPeriod, secondPeriod)
	isValidBackward := isValidOrder(reverse(flags), firstPeriod, secondPeriod)
	if isValidForward && isValidBackward {
		return "both"
	} else if isValidForward {
		return "forward"
	} else if isValidBackward {
		return "backward"
	}
	return "fantasy"
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	var flags string
	var firstPeriod string
	var secondPeriod string
	fmt.Fscanf(reader, "%s\n", &flags)
	fmt.Fscanf(reader, "%s\n", &firstPeriod)
	fmt.Fscanf(reader, "%s\n", &secondPeriod)
	fmt.Fprintf(writer, "%s\n", Solve(flags, firstPeriod, secondPeriod))
}