Problem:
Score : 500 points

Problem Statement

You are given a string S of length N consisting of lowercase English letters.

Process Q queries of the following two types:

Type 1: change the i_q-th character of S to c_q. (Do nothing if the i_q-th character is already c_q.)

Type 2: answer the number of different characters occurring in the substring of S between the l_q-th and r_q-th characters (inclusive).

Constraints

N, Q, i_q, l_q, and r_q are integers.

S is a string consisting of lowercase English letters.

c_q is a lowercase English letter.

1 \leq N \leq 500000

1 \leq Q \leq 20000

|S| = N

1 \leq i_q \leq N

1 \leq l_q \leq r_q \leq N

There is at least one query of type 2 in each testcase.

Input

Input is given from Standard Input in the following format:

N
S
Q
Query_1
\vdots
Query_Q

Here, Query_i in the 4-th through (Q+3)-th lines is one of the following:

1 i_q c_q

2 l_q r_q

Output

For each query of type 2, print a line containing the answer.

Sample Input 1

7
abcdbbd
6
2 3 6
1 5 z
2 1 1
1 4 a
1 7 d
2 1 7

Sample Output 1

3
1
5

In the first query, cdbb contains three kinds of letters: b , c , and d, so we print 3.

In the second query, S is modified to abcdzbd.

In the third query, a contains one kind of letter: a, so we print 1.

In the fourth query, S is modified to abcazbd.

In the fifth query, S does not change and is still abcazbd.

In the sixth query, abcazbd contains five kinds of letters: a, b, c, d, and z, so we print 5.

Solution in Kotlin (1.0.0) (judge verdict: Accepted)

import java.util.*

fun main(args: Array<String>) = abc157e()

fun abc157e() {
    val n = readLine()!!.toInt()
    val s = readLine()!!
    val q = readLine()!!.toInt()
    val queries = (1..q).map {
        readLine()!!.split(' ').map { it }
            .let { Query(if (it[0].toInt() == 1) QueryType.UPDATE else QueryType.GET, it[1].toInt(), it[2]) }
    }

    val arr = IntArray(n)
    s.forEachIndexed { index, c -> arr[index] = charToBit(c) }

    val st = SegmentTree(arr, Int::or)
    val answer = StringBuilder()

    for ((type, x, y) in queries) {
        when (type) {
            QueryType.UPDATE -> st[x - 1] = y[0]
            else -> answer.appendln(st[x - 1..y.toInt() - 1])
        }
    }

    print(answer)
}

private fun charToBit(char: Char) = Math.pow(2.0, (char - 'a').toDouble()).toInt()

private data class Query(val type: QueryType, val x: Int, val y: String)
private enum class QueryType { UPDATE, GET }

private class SegmentTree(init: IntArray, val monad: (Int, Int) -> Int) {
    val indices: Int
    val nodes: IntArray

    init {
        var indices = 1
        while (indices < init.size) indices = indices shl 1
        val nodes = IntArray(2 * indices - 1)
        for (i in init.indices) nodes[i + indices - 1] = init[i]
        for (i in indices - 2 downTo 0) nodes[i] = monad(nodes[2 * i + 1], nodes[2 * i + 2])
        this.indices = indices
        this.nodes = nodes
    }

    operator fun set(x: Int, value: Char) {
        var index = x + indices - 1
        nodes[index] = charToBit(value)
        while (index > 0) {
            index = (index - 1) / 2
            nodes[index] = monad(nodes[2 * index + 1], nodes[2 * index + 2])
        }
    }

    operator fun get(range: IntRange): Int =
        BitSet.valueOf(longArrayOf(get(range.first, range.last + 1).toLong())).cardinality()

    fun get(a: Int, b: Int, k: Int = 0, l: Int = 0, r: Int = indices): Int {
        if (r <= a || b <= l) return 0
        if (a <= l && r <= b) return nodes[k]
        return monad(
            get(a, b, 2 * k + 1, l, (l + r) / 2),
            get(a, b, 2 * k + 2, (l + r) / 2, r)
        )
    }
}