← Home
```go
package main

import (
	"bufio"
	"fmt"
	"math/bits"
	"os"
)

type Ray struct {
	x, y int64
}

var (
	count0        int
	rayCounts     = make(map[Ray]int)
	oppositePairs int
	badPairs      int
	tree          = &Treap{}
	bottles       = make(map[int]Ray)
	bottleOrigin  = make(map[int]bool)
)

func gcd(a, b int64) int64 {
	if a < 0 {
		a = -a
	}
	if b < 0 {
		b = -b
	}
	for b != 0 {
		a, b = b, a%b
	}
	return a
}

func normalize(x, y int64) Ray {
	g := gcd(x, y)
	return Ray{x / g, y / g}
}

func opposite(r Ray) Ray {
	return Ray{-r.x, -r.y}
}

func mul128(a, b int64) (hi int64, lo uint64) {
	sign := int64(1)
	if a < 0 {
		a = -a
		sign = -sign
	}
	if b < 0 {
		b = -b
		sign = -sign
	}
	hiU, lo := bits.Mul64(uint64(a), uint64(b))
	if sign < 0 {
		lo = ^lo + 1
		hiU = ^hiU
		if lo == 0 {
			hiU++
		}
	}
	return int64(hiU), lo
}

func cmp128(hi1 int64, lo1 uint64, hi2 int64, lo2 uint64) int {
	if hi1 != hi2 {
		if hi1 < hi2 {
			return -1
		}
		return 1
	}
	if lo1 != lo2 {
		if lo1 < lo2 {
			return -1
		}
		return 1
	}
	return 0
}

func crossSign(a, b Ray) int {
	hi1, lo1 := mul128(a.x, b.y)
	hi2, lo2 := mul128(a.y, b.x)
	return cmp128(hi1, lo1, hi2, lo2)
}

func half(a Ray) int {
	if a.y > 0 || (a.y == 0 && a.x > 0) {
		return 1
	}
	return 0
}

func cmpRay(a, b Ray) int {
	ha := half(a)
	hb := half(b)
	if ha != hb {
		if ha > hb {
			return -1
		}
		return 1
	}
	c := crossSign(a, b)
	if c > 0 {
		return -1
	}
	if c < 0 {
		return 1
	}
	return 0
}

type Node struct {
	key      Ray
	priority uint32
	left     *Node
	right    *Node
}

type Treap struct {
	root *Node
	size int
}

var seed uint32 = 12345

func fastRand() uint32 {
	seed ^= seed << 13
	seed ^= seed >> 17
	seed ^= seed << 5
	return seed
}

func (t *Treap) Size() int {
	return t.size
}

func rightRotate(y *Node) *Node {
	x := y.left
	y.left = x.right
	x.right = y
	return x
}

func leftRotate(x *Node) *Node {
	y := x.right
	x.right = y.left
	y.left = x
	return y
}

func insertNode(root *Node, key Ray) *Node {
	if root == nil {
		return &Node{key: key, priority: fastRand()}
	}
	cmp := cmpRay(key, root.key)
	if cmp < 0 {
		root.left = insertNode(root.left, key)
		if root.left.priority > root.priority {
			root = rightRotate(root)
		}
	} else if cmp > 0 {
		root.right = insertNode(root.right, key)
		if root.right.priority > root.priority {
			root = leftRotate(root)
		}
	}
	return root
}

func (t *Treap) Insert(key Ray) {
	t.root = insertNode(t.root, key)
	t.size++
}

func deleteNode(root *Node, key Ray) *Node {
	if root == nil {
		return nil
	}
	cmp := cmpRay(key, root.key)
	if cmp < 0 {
		root.left = deleteNode(root.left, key)
	} else if cmp > 0 {
		root.right = deleteNode(root.right, key)
	} else {
		if root.left == nil {
			return root.right
		} else if root.right == nil {
			return root.left
		}
		if root.left.priority > root.right.priority {
			root = rightRotate(root)
			root.right = deleteNode(root.right, key)
		} else {
			root = leftRotate(root)
			root.left = deleteNode(root.left, key)
		}
	}
	return root
}

func (t *Treap) Delete(key Ray) {
	t.root = deleteNode(t.root, key)
	t.size--
}

func (t *Treap) Min() Ray {
	curr := t.root
	for curr.left != nil {
		curr = curr.left
	}
	return curr.key
}

func (t *Treap) Max() Ray {
	curr := t.root
	for curr.right != nil {
		curr = curr.right
	}
	return curr.key
}

func (t *Treap) Pred(key Ray) Ray {
	var best *Node
	curr := t.root
	for curr != nil {
		if cmpRay(curr.key, key) < 0 {
			best = curr
			curr = curr.right
		} else {
			curr = curr.left
		}
	}
	if best == nil {
		return t.Max()
	}
	return best.key
}

func (t *Treap) Succ(key Ray) Ray {
	var best *Node
	curr := t.root
	for curr != nil {
		if cmpRay(curr.key, key) > 0 {
			best = curr
			curr = curr.left
		} else {
			curr = curr.right
		}
	}
	if best == nil {
		return t.Min()
	}
	return best.key
}

func insertRay(r Ray) {
	if tree.Size() == 0 {
		tree.Insert(r)
		return
	}
	p := tree.Pred(r)
	s := tree.Succ(r)

	if crossSign(p, s) < 0 {
		badPairs--
	}
	if crossSign(p, r) < 0 {
		badPairs++
	}
	if crossSign(r, s) < 0 {
		badPairs++
	}
	tree.Insert(r)
}

func removeRay(r Ray) {
	if tree.Size() == 1 {
		tree.Delete(r)
		return
	}
	p := tree.Pred(r)
	s := tree.Succ(r)

	if crossSign(p, r) < 0 {
		badPairs--
	}
	if crossSign(r, s) < 0 {
		badPairs--
	}
	if crossSign(p, s) < 0 {
		badPairs++
	}
	tree.Delete(r)
}

func nextInt64(r *bufio.Reader) int64 {
	var n int64
	var c byte
	var err error
	for {
		c, err = r.ReadByte()
		if err != nil || (c >= '0' && c <= '9') || c == '-' {
			break
		}
	}
	sign := int64(1)
	if c == '-' {
		sign = -1
		c, _ = r.ReadByte()
	}
	for err == nil && c >= '0' && c <= '9' {
		n = n*10 + int64(c-'0')
		c, err = r.ReadByte()
	}
	return n * sign
}

func nextChar(r *bufio.Reader) byte {
	var c byte
	var err error
	for {
		c, err = r.ReadByte()
		if err != nil || (c >= 'A' && c <= 'Z') {
			break
		}
	}
	return c
}

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

	Sf := nextInt64(reader)
	Pf := nextInt64(reader)
	Gf := nextInt64(reader)
	N := int(nextInt64(reader))

	bottleID := 1
	for i := 0; i < N; i++ {
		op := nextChar(reader)
		if op == 'A' {
			Si := nextInt64(reader)
			Pi := nextInt64(reader)
			Gi := nextInt64(reader)
			X := Si*(Sf+Pf+Gf) - Sf*(Si+Pi+Gi)
			Y := Pi*(Sf+Pf+Gf) - Pf*(Si+Pi+Gi)
			if X == 0 && Y == 0 {
				count0++
				bottleOrigin[bottleID] = true
			} else {
				r := normalize(X, Y)
				bottles[bottleID] = r
				if rayCounts[r] == 0 {
					if rayCounts[opposite(r)] > 0 {
						oppositePairs++
					}
					insertRay(r)
				}
				rayCounts[r]++
			}
			bottleID++
		} else if op == 'R' {
			r_i := int(nextInt64(reader))
			if bottleOrigin[r_i] {
				count0--
				delete(bottleOrigin, r_i)
			} else {
				r := bottles[r_i]
				rayCounts[r]--
				if rayCounts[r] == 0 {
					if rayCounts[opposite(r)] > 0 {
						oppositePairs--
					}
					removeRay(r)
				}
				delete(bottles, r_i)
			}
		}

		if count0 > 0 {
			fmt.Fprintln(writer, 1)
		} else if oppositePairs > 0 {
			fmt.Fprintln(writer, 2)
		} else if tree.Size() >= 3 && badPairs == 0 {
			fmt.Fprintln(writer, 3)
		} else {
			fmt.Fprintln(writer, 0)
		}
	}
}
```