output_description: For each query of type 2, print a line containing the answer.
  
  * * *
input_description: 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
attempt: #!/usr/bin/env python3
  
  import sys
  
  DEBUG = False
  
  
  class SegmentTree:
  
      def __init__(self, n):
          self.n = 1
          while self.n < n:
              self.n *= 2
          self.fillval = 0
          self.nodes = [0 for _ in range(self.n)]
  
      def update(self, idx, val):
          nodes = self.nodes
  
          idx += self.n - 1
          nodes[idx] = val
          while idx > 0:
              idx = (idx - 1) // 2
              nodes[idx] = nodes[idx * 2 + 1] | nodes[idx * 2 + 2]
  
      def query(self, l, r):
          fillval = self.fillval
          nodes = self.nodes
  
          def _query(l, r, scope_idx, scope_l, scope_r):
              if r <= scope_l or l >= scope_r:
                  return fillval
              if l <= scope_l and r >= scope_r:
                  return nodes[scope_idx]
              vl = _query(l, r, scope_idx * 2 + 1, scope_l, (scope_l + scope_r) // 2)
              vr = _query(l, r, scope_idx * 2 + 2, (scope_l + scope_r) // 2, scope_r)
              return vl | vr
  
          return _query(l, r, 0, 0, self.n)
  
  
  def read(t=str):
      return t(sys.stdin.readline().rstrip())
  
  
  def read_list(t=str, sep=" "):
      return [t(s) for s in sys.stdin.readline().rstrip().split(sep)]
  
  
  def dprint(*args, **kwargs):
      if DEBUG:
          print(*args, **kwargs)
      return
  
  
  class LetterAppearance:
      def __init__(self, chars):
          self.chars_app = SegmentTree(len(chars))
          for i in range(0, len(chars)):
              bit = ord(chars[i]) - ord("a")
              self.chars_app.update(i, 1 << bit)
  
      def replace(self, pos, char):
          bit = ord(char) - ord("a")
          self.chars_app.update(pos, 1 << bit)
  
      def query(self, l, r):
          return bin(self.chars_app.query(l, r)).count("1")
  
  
  def main():
      read()
      s = read()
      apps = LetterAppearance(s)
      nr_q = read(int)
      for i in range(0, nr_q):
          q = read_list()
          if q[0] == "1":
              _, i, c = q  # i_q in the question starts from 1, not 0
              apps.replace(int(i) - 1, c)
          else:
              _, l, r = q  # l_q and r_q in the question start from 1, not 0
              print(
                  apps.query(int(l) - 1, int(r) - 1 + 1)
              )  # query in the question includes both edges
  
  
  if __name__ == "__main__":
      main()
  
problem_description: 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).
samples: [{"input": "7\n    abcdbbd\n    6\n    2 3 6\n    1 5 z\n    2 1 1\n    1 4 a\n    1 7 d\n    2 1 7", "output": "3\n    1\n    5\n    \n\nIn the first query, `cdbb` contains three kinds of letters: `b` , `c` , and\n`d`, so we print 3.\n\nIn the second query, S is modified to `abcdzbd`.\n\nIn the third query, `a` contains one kind of letter: `a`, so we print 1.\n\nIn the fourth query, S is modified to `abcazbd`.\n\nIn the fifth query, S does not change and is still `abcazbd`.\n\nIn the sixth query, `abcazbd` contains five kinds of letters: `a`, `b`, `c`,\n`d`, and `z`, so we print 5."}]