← Home
package main

import (
	"bufio"
	"os"
	"strconv"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)

	buf := make([]byte, 0, 1024*1024)
	scanner.Buffer(buf, 10*1024*1024)

	if !scanner.Scan() {
		return
	}
	q, _ := strconv.Atoi(scanner.Text())

	up := make([][20]int, q+1)
	val := make([]int, q+1)

	stack := make([]int, 0, q+1)
	stack = append(stack, 0)

	queries := make([]int, 0, q)

	id := 0

	for i := 0; i < q; i++ {
		scanner.Scan()
		op := scanner.Text()
		if op == "+" {
			scanner.Scan()
			x, _ := strconv.Atoi(scanner.Text())
			id++
			val[id] = x
			p := stack[len(stack)-1]
			up[id][0] = p
			for j := 1; j < 20; j++ {
				up[id][j] = up[up[id][j-1]][j-1]
			}
			stack = append(stack, id)
		} else if op == "-" {
			scanner.Scan()
			k, _ := strconv.Atoi(scanner.Text())
			curr := stack[len(stack)-1]
			for j := 19; j >= 0; j-- {
				if (k & (1 << j)) != 0 {
					curr = up[curr][j]
				}
			}
			stack = append(stack, curr)
		} else if op == "!" {
			stack = stack[:len(stack)-1]
		} else if op == "?" {
			queries = append(queries, stack[len(stack)-1])
		}
	}

	head := make([]int, id+1)
	for i := range head {
		head[i] = -1
	}
	next := make([]int, id+1)

	for i := 1; i <= id; i++ {
		p := up[i][0]
		next[i] = head[p]
		head[p] = i
	}

	ansAt := make([]int, id+1)
	freq := make([]int, 1000005)
	distinct := 0

	var dfs func(int)
	dfs = func(u int) {
		ansAt[u] = distinct
		for v := head[u]; v != -1; v = next[v] {
			x := val[v]
			if freq[x] == 0 {
				distinct++
			}
			freq[x]++

			dfs(v)

			freq[x]--
			if freq[x] == 0 {
				distinct--
			}
		}
	}

	dfs(0)

	out := bufio.NewWriter(os.Stdout)
	for _, qNode := range queries {
		out.WriteString(strconv.Itoa(ansAt[qNode]))
		out.WriteByte('\n')
	}
	out.Flush()
}