← Home
```go
package main

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

type BIT struct {
    n    int
    tree []int
}

func newBIT(n int) *BIT {
    return &BIT{n: n, tree: make([]int, n+1)}
}

func (b *BIT) add(i int, delta int) {
    for i <= b.n {
        b.tree[i] += delta
        i += i & -i
    }
}

func (b *BIT) sum(i int) int {
    s := 0
    for i > 0 {
        s += b.tree[i]
        i -= i & -i
    }
    return s
}

func (b *BIT) rangeSum(l, r int) int {
    return b.sum(r) - b.sum(l-1)
}

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    scanner.Buffer(make([]byte, 0, 1<<20), 1<<20)
    scanner.Scan()
    s := scanner.Text()
    n := len(s)
    bits := make([]*BIT, 26)
    for i := 0; i < 26; i++ {
        bits[i] = newBIT(n)
    }
    for i, c := range s {
        bits[c-'a'].add(i+1, 1)
    }
    scanner.Scan()
    q, _ := strconv.Atoi(scanner.Text())
    var output strings.Builder
    for i := 0; i < q; i++ {
        scanner.Scan()
        line := scanner.Text()
        parts := strings.Fields(line)
        if parts[0] == "1" {
            pos, _ := strconv.Atoi(parts[1])
            newC := parts[2][0]
            oldC := s[pos-1]
            if oldC != newC {
                bits[oldC-'a'].add(pos, -1)
                bits[newC-'a'].add(pos, 1)
                sb := []byte(s)
                sb[pos-1] = newC
                s = string(sb)
            }
        } else {
            l, _ := strconv.Atoi(parts[1])
            r, _ := strconv.Atoi(parts[2])
            cnt := 0
            for j := 0; j < 26; j++ {
                if bits[j].rangeSum(l, r) > 0 {
                    cnt++
                }
            }
            output.WriteString(strconv.Itoa(cnt))
            output.WriteByte('\n')
        }
    }
    fmt.Print(output.String())
}
```