← Home
package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"sort"
)

type Query struct {
	typ int
	x   int
	y   int
}

func main() {
	buffer, _ := ioutil.ReadAll(os.Stdin)
	pos := 0
	readInt := func() int {
		for pos < len(buffer) && buffer[pos] <= ' ' {
			pos++
		}
		if pos >= len(buffer) {
			return 0
		}
		res := 0
		for pos < len(buffer) && buffer[pos] > ' ' {
			res = res*10 + int(buffer[pos]-'0')
			pos++
		}
		return res
	}

	n := readInt()
	if n == 0 {
		return
	}
	m := readInt()

	queries := make([]Query, m)
	for i := 0; i < m; i++ {
		queries[i].typ = readInt()
		queries[i].x = readInt()
		queries[i].y = readInt()
	}

	B := 700

	S := make([]uint64, 0, m)
	S_alt := make([]uint64, 0, m)
	F := make([]uint64, 0, m)
	C := make([]uint64, 0, 2*B)
	C_true := make([]uint64, 0, 2*B)
	state := make([]bool, 2*B)

	base_parent := make([]int, n+1)
	base_size := make([]int, n+1)
	small_parent := make([]int, n+1)

	base_find := func(i int) int {
		root := i
		for root != base_parent[root] {
			root = base_parent[root]
		}
		curr := i
		for curr != root {
			nxt := base_parent[curr]
			base_parent[curr] = root
			curr = nxt
		}
		return root
	}

	base_union := func(i, j int) {
		rootI := base_find(i)
		rootJ := base_find(j)
		if rootI != rootJ {
			if base_size[rootI] < base_size[rootJ] {
				rootI, rootJ = rootJ, rootI
			}
			base_parent[rootJ] = rootI
			base_size[rootI] += base_size[rootJ]
		}
	}

	small_find := func(i int) int {
		root := i
		for root != small_parent[root] {
			root = small_parent[root]
		}
		curr := i
		for curr != root {
			nxt := small_parent[curr]
			small_parent[curr] = root
			curr = nxt
		}
		return root
	}

	small_union := func(i, j int) {
		rootI := small_find(i)
		rootJ := small_find(j)
		if rootI != rootJ {
			small_parent[rootI] = rootJ
		}
	}

	results := make([]byte, 0, m)
	last := 0

	for b := 0; b*B < m; b++ {
		start := b * B
		end := start + B
		if end > m {
			end = m
		}

		C = C[:0]
		for k := start; k < end; k++ {
			q := queries[k]
			if q.typ == 1 {
				u0 := (q.x-1)%n + 1
				v0 := (q.y-1)%n + 1
				if u0 > v0 {
					u0, v0 = v0, u0
				}
				C = append(C, (uint64(u0)<<32)|uint64(v0))

				u1 := q.x%n + 1
				v1 := q.y%n + 1
				if u1 > v1 {
					u1, v1 = v1, u1
				}
				C = append(C, (uint64(u1)<<32)|uint64(v1))
			}
		}

		if len(C) > 0 {
			sort.Slice(C, func(i, j int) bool { return C[i] < C[j] })
			uniq := 0
			for i := 0; i < len(C); i++ {
				if i == 0 || C[i] != C[i-1] {
					C[uniq] = C[i]
					uniq++
				}
			}
			C = C[:uniq]
		}

		if len(state) < len(C) {
			state = make([]bool, len(C))
		} else {
			state = state[:len(C)]
		}
		for i := 0; i < len(C); i++ {
			state[i] = false
		}

		F = F[:0]
		i, j := 0, 0
		for i < len(S) && j < len(C) {
			if S[i] < C[j] {
				F = append(F, S[i])
				i++
			} else if S[i] > C[j] {
				j++
			} else {
				state[j] = true
				i++
				j++
			}
		}
		for i < len(S) {
			F = append(F, S[i])
			i++
		}

		for i := 1; i <= n; i++ {
			base_parent[i] = i
			base_size[i] = 1
		}
		for _, e := range F {
			base_union(int(e>>32), int(e&0xFFFFFFFF))
		}

		for k := start; k < end; k++ {
			q := queries[k]
			u := (q.x+last-1)%n + 1
			v := (q.y+last-1)%n + 1
			if u > v {
				u, v = v, u
			}
			e := (uint64(u) << 32) | uint64(v)

			if q.typ == 1 {
				l, r := 0, len(C)-1
				idx := -1
				for l <= r {
					mid := l + (r - l) / 2
					if C[mid] == e {
						idx = mid
						break
					} else if C[mid] < e {
						l = mid + 1
					} else {
						r = mid - 1
					}
				}
				if idx != -1 {
					state[idx] = !state[idx]
				}
			} else {
				cu := base_find(u)
				cv := base_find(v)
				if cu == cv {
					last = 1
				} else {
					small_parent[cu] = cu
					small_parent[cv] = cv
					for idx := 0; idx < len(C); idx++ {
						if state[idx] {
							uc := base_find(int(C[idx] >> 32))
							vc := base_find(int(C[idx] & 0xFFFFFFFF))
							small_parent[uc] = uc
							small_parent[vc] = vc
						}
					}
					for idx := 0; idx < len(C); idx++ {
						if state[idx] {
							uc := base_find(int(C[idx] >> 32))
							vc := base_find(int(C[idx] & 0xFFFFFFFF))
							small_union(uc, vc)
						}
					}
					if small_find(cu) == small_find(cv) {
						last = 1
					} else {
						last = 0
					}
				}
				results = append(results, byte('0'+last))
			}
		}

		C_true = C_true[:0]
		for idx := 0; idx < len(C); idx++ {
			if state[idx] {
				C_true = append(C_true, C[idx])
			}
		}

		S_alt = S_alt[:0]
		i, j = 0, 0
		for i < len(F) && j < len(C_true) {
			if F[i] < C_true[j] {
				S_alt = append(S_alt, F[i])
				i++
			} else if F[i] > C_true[j] {
				S_alt = append(S_alt, C_true[j])
				j++
			} else {
				S_alt = append(S_alt, F[i])
				i++
				j++
			}
		}
		for i < len(F) {
			S_alt = append(S_alt, F[i])
			i++
		}
		for j < len(C_true) {
			S_alt = append(S_alt, C_true[j])
			j++
		}
		S, S_alt = S_alt, S
	}

	os.Stdout.Write(results)
	fmt.Println()
}