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 (Python):
"""SegTree, 遅い、、、

Returns:
    [type]: [description]
"""
import sys
sys.setrecursionlimit(4100000)

import math

import logging

logging.basicConfig(level=logging.DEBUG)

logger = logging.getLogger(__name__)


class SegTree:
    """ノードで集合をもつ
    
    Returns:
        [type]: [description]
    """
    def __init__(self, s):

        N = len(s)

        self.default = 0

        
        _n = N
        self.n = 1
        while (self.n < _n):
            self.n = self.n * 2

        self.tree = [self.default for _ in range(2 * self.n - 1)]

        for i, c in enumerate(s):
            self.update(i, c)

    def update(self, i, x):
        i = i + self.n - 1
        self.tree[i] = x

        
        while (i > 0):
            i = (i - 1) // 2
            l = self.tree[i * 2 + 1]
            r = self.tree[i * 2 + 2]
            self.tree[i] = l | r

    def query(
        self,
        query_start,
        query_end,  
        i_parent=0,
        parent_start=0,
        parent_end=None  
    ):
        if parent_end is None:
            parent_end = self.n
        if (query_end <= parent_start
                or parent_end <= query_start):  
            return self.default
        elif (query_start <= parent_start
              and parent_end <= query_end):  
            return self.tree[i_parent]
        else:
            return self.query(query_start, query_end, 2 * i_parent + 1,
                           parent_start, (parent_start + parent_end) // 2) | \
                self.query(query_start, query_end, 2 * i_parent + 2,
                           (parent_start + parent_end) // 2, parent_end)


def resolve():
    N = [int(x) for x in sys.stdin.readline().split()][0]  
    S = [x for x in sys.stdin.readline().split()][0]  
    Q = [int(x) for x in sys.stdin.readline().split()][0]  

    
    

    
    
    grid = [[x for x in sys.stdin.readline().split()]
            for _ in range(Q)]  

    seg = SegTree([1 << ord(c) - 97 for c in S])

    for _type, a, b in grid:
        if _type == '1':
            a = int(a) - 1
            bit = 1 << (ord(b) - 97)
            seg.update(a, bit)

        else:
            a = int(a) - 1
            b = int(b) - 1
            ret = seg.query(a, b + 1)
            print(bin(ret)[2:].count('1'))


if __name__ == "__main__":
    resolve()





import sys
from io import StringIO
import unittest


class TestClass(unittest.TestCase):
    def assertIO(self, input, output):
        stdout, stdin = sys.stdout, sys.stdin
        sys.stdout, sys.stdin = StringIO(), StringIO(input)
        resolve()
        sys.stdout.seek(0)
        out = sys.stdout.read()[:-1]
        sys.stdout, sys.stdin = stdout, stdin
        self.assertEqual(out, output)

    def test_入力例_1(self):
        input = """7
abcdbbd
6
2 3 6
1 5 z
2 1 1
1 4 a
1 7 d
2 1 7"""
        output = """3
1
5"""
        self.assertIO(input, output)

    def test_入力例_2(self):
        input = """7
abcdbbd
6
2 3 6
1 5 z
2 1 1
1 4 a
1 7 d
2 1 7"""
        output = """3
1
5"""
        self.assertIO(input, output)

Solution (Python):
import sys
sr = lambda: sys.stdin.readline().rstrip()
ir = lambda: int(sr())
lr = lambda: list(map(int, sr().split()))
from bisect import bisect_left
def resolve():
    N = ir()
    S = list(sr())
    a = [[] for _ in range(26)]
    for i, s in enumerate(S):
        a[ord(s)-ord('a')].append(i)
    Q = ir()
    for i in range(Q):
        x, y, z = sr().split()
        if x == '1':
            y = int(y)-1
            if S[y] == z:
                continue
            u = ord(S[y])-ord('a')
            l = bisect_left(a[u], y)
            a[u].pop(l)
            v = ord(z)-ord('a')
            l = bisect_left(a[v], y)
            a[v].insert(l, y)
            S[y] = z
        else:
            y = int(y)-1
            z = int(z)-1
            ans = 0
            for i in range(26):
                l = bisect_left(a[i], y)
                if l == len(a[i]):
                    continue
                elif a[i][l] <= z:
                    ans += 1
            print(ans)
resolve()

Solution (Python):
class SegmentTree:
    def __init__(self, data):
        
        self.default_value = 0
        
        self.power = 2 ** (N - 1).bit_length()
        self.node = [self.default_value] * 2 * self.power
        for i in range(N):
            self.node[i + self.power - 1] = 1 << (ord(data[i]) - 97)
        for i in range(self.power - 2, -1, -1):
            self.node[i] = self.node[2 * i + 1] | self.node[2 * i + 2]

    def update(self, k, x):
        k += self.power - 1
        self.node[k] = 1 << (ord(x) - 97)
        while k:
            k = (k - 1) // 2
            self.node[k] = self.node[k * 2 + 1] | self.node[k * 2 + 2]

    def query(self, left, right):
        if right <= left:
            return self.default_value
        left += self.power - 1
        right += self.power - 2
        ret = self.default_value
        while right - left > 1:
            if left & 1 == 0:
                ret = ret | self.node[left]
            if right & 1 == 1:
                ret = ret | self.node[right]
                right -= 1
            left = left // 2
            right = (right - 1) // 2
        if left == right:
            ret = ret | self.node[left]
        else:
            ret = (ret | self.node[left]) | self.node[right]
        return ret


N = int(input())
S = list(input().strip())
Q = int(input())
MAX_DIGIT = 26

st = SegmentTree(S)

for i in range(Q):
    q, a, b = map(str, input().split())
    if int(q) == 1:
        a = int(a) - 1
        st.update(a, b)
    if int(q) == 2:
        a = int(a) - 1
        b = int(b)
        res = st.query(a, b)
        ans = 0
        for d in range(MAX_DIGIT):
            if res >> d & 1:
                ans += 1
        print(ans)

Solution (Python):
N = int(input())
S = list(input())
Q = int(input())

l = 2**((N-1).bit_length())

data = [0] * (2*l)

str2bin = lambda x : 1 << (ord(x) - ord('a'))
    
for i in range(N):
    data[l+i] = str2bin(S[i])
for i in range(l-1,0,-1):
    data[i] = data[2*i] | data[2*i+1]

for cnt in range(Q):
    a,b,c = input().split()
    a = int(a)
    b = int(b)
    if a == 1:
        n = l + b - 1
        data[n] = str2bin(c)
        n //= 2
        while n > 0:
            data[n] = data[2*n] | data[2*n+1]
            n = n // 2
    else:
        c = int(c)
        i = b + l -1
        j = c + l
        res = 0
        while j-i > 0:
            if i & 1:
                res |= data[i]
                i += 1
            if j & 1:
                res |= data[j-1]
                j -= 1
            i //= 2
            j //= 2
        print(bin(res).count('1'))

Solution (Python):
class SegmentTree:
    def __init__(self, data):
        
        self.ide_ele = 0
        
        self.num = 2 ** (N - 1).bit_length()
        self.seg = [self.ide_ele] * 2 * self.num
        for i in range(N):
            self.seg[i + self.num - 1] = 1 << (ord(data[i]) - 97)
        for i in range(self.num - 2, -1, -1):
            self.seg[i] = self.seg[2 * i + 1] | self.seg[2 * i + 2]

    def update(self, k, x):
        k += self.num - 1
        self.seg[k] = 1 << (ord(x) - 97)
        while k:
            k = (k - 1) // 2
            self.seg[k] = self.seg[k * 2 + 1] | self.seg[k * 2 + 2]

    def query(self, left, right):
        if right <= left:
            return self.ide_ele
        left += self.num - 1
        right += self.num - 2
        res = self.ide_ele
        while right - left > 1:
            if left & 1 == 0:
                res = res | self.seg[left]
            if right & 1 == 1:
                res = res | self.seg[right]
                right -= 1
            left = left // 2
            right = (right - 1) // 2
        if left == right:
            res = res | self.seg[left]
        else:
            res = (res | self.seg[left]) | self.seg[right]
        return res


N = int(input())
S = list(input().strip())
Q = int(input())
MAX_DIGIT = 26
st = SegmentTree(S)


for i in range(Q):
    q, a, b = map(str, input().split())
    if int(q) == 1:
        a = int(a) - 1
        st.update(a, b)
    if int(q) == 2:
        a = int(a) - 1
        b = int(b)
        res = st.query(a, b)
        print(str(bin(res)).count('1'))

Solution (Python):
import sys,collections as cl,bisect as bs
sys.setrecursionlimit(100000)
input = sys.stdin.readline
mod = 10**9+7
Max = sys.maxsize
def l(): 
    return list(map(int,input().split()))
def m(): 
    return map(int,input().split())
def onem(): 
    return int(input())
def s(x): 
    a = []
    aa = x[0]
    su = 1
    for i in range(len(x)-1):
        if aa != x[i+1]:
            a.append([aa,su])
            aa = x[i+1]
            su = 1
        else:
            su += 1
    a.append([aa,su])
    return a
def jo(x): 
    return " ".join(map(str,x))
def max2(x): 
    return max(map(max,x))
def In(x,a): 
    k = bs.bisect_left(a,x)
    if k != len(a) and a[k] ==  x:
        return True
    else:
        return False
"""
def nibu(x,n,r):
    ll = 0
    rr = r
    while True:
        mid = (ll+rr)//2

    if rr == mid:
        return ll
    if (ここに評価入れる):
        rr = mid
    else:
        ll = mid+1
"""
class SegmentTree:
    def segfunc(self,x,y):
        
        po = [0 for i in range(26)]
        for i in range(26):
            po[i] = x[i]+y[i]
        return po

    
    def __init__(self,n,init,ide_ele):
        self.n = n
        self.ide_ele = ide_ele
        self.num = 2**(n-1).bit_length()
        self.seg = [ide_ele for i in range(2*self.num)]
        for i in range(n):
            self.seg[i+self.num-1] = init[i]
        for i in range(self.num-2,-1,-1):
            self.seg[i] = self.segfunc(self.seg[2*i+1],self.seg[2*i+2])
    
    
    def update(self,k,x):
        k += self.num-1
        self.seg[k] = x
        while k:
            k = (k-1)//2
            self.seg[k] = self.segfunc(self.seg[2*k+1],self.seg[2*k+2])
    
    def query(self,p,q):
        if q <= p:
            return [1 if i == 0 else 0 for i in range(26)]
        p += self.num-1
        q += self.num-2
        res = self.ide_ele
        while q-p > 1:
            if p & 1 == 0:
                res = self.segfunc(res,self.seg[p])
            if q & 1 == 1:
                res = self.segfunc(res,self.seg[q])
                q -= 1
            p //= 2
            q = (q-1)//2
        if p == q:
            res = self.segfunc(res,self.seg[p])
        else:
            res = self.segfunc(self.segfunc(res,self.seg[p]),self.seg[q])
        return res

def solver():
    n = onem()
    s = input().split()[0]
    po = onem()

    abc = [[0 for i in range(26)] for j in range(n)]

    for i in range(n):
        ppp = s[i]
        abc[i][ord(s[i]) - 97] += 1

    Se = SegmentTree(n,abc,[0 for i in range(26)])



    for i in range(po):
        a,b,c = input().split()
        a = int(a)
        b = int(b)
        if a == 1:
            ppp = [0] * 26
            ppp[ord(c) - 97] = 1
            Se.update(b-1,ppp)      
        else:
            c = int(c)
            op = Se.query(b-1,c)
            co = 0
            for i in range(26):
                if op[i] >= 1:
                    co += 1
            print(co)


if __name__ == "__main__":
    solver()

Solution (Python):
import sys

read = sys.stdin.read
readline = sys.stdin.readline


class BIT:
    def __init__(self, n):
        self.n = n
        self.tree = [[0] * (n + 1) for _ in range(26)]

    def bit_query(self, character, idx):
        if idx == 0:
            return 0
        sum_of_query = 0
        while idx > 0:
            sum_of_query += self.tree[character][idx]
            idx -= idx & (-idx)
        return sum_of_query

    def update(self, character, idx, x):
        while idx <= self.n:
            self.tree[character][idx] += x
            idx += idx & (-idx)
        return


N = int(input())
S = [i - 97 for i in map(ord, list(input()))]
S = [-1] + S
Q, *query = map(str, read().split())
bit = BIT(N)
for idx, i in enumerate(S[1:], 1):
    bit.update(i, idx, 1)
for a, b, c in zip(*[iter(query)] * 3):
    b = int(b)
    if a == '1':
        c = ord(c) - 97
        if S[b] == c:
            continue
        bit.update(c, b, 1)
        bit.update(S[b], b, -1)
        S[b] = c
    else:
        c = int(c)
        print(sum(1 for i in range(26) if bit.bit_query(i, c) - bit.bit_query(i, b - 1) > 0))

Solution (Python):

import sys, math, itertools, collections, bisect
input = lambda: sys.stdin.buffer.readline().rstrip().decode('utf-8')
inf = float('inf') ;mod = 10**9+7
mans = inf ;ans = 0 ;count = 0 ;pro = 1

class SegmentTree:
  __slots__ = ['ide','n','seg','segfunc']

  def __init__(self,size,func,element):
    self.segfunc = func
    self.ide = element
    
    self.n = 2 ** (n-1).bit_length()
    
    
    self.seg = [self.ide] * (2*self.n-1)

  def apply(self,array):
    arraysize = len(array)
    
    for i in range(arraysize):
      self.seg[self.n-1+i] = array[i]
    
    for i in range(self.n-2,-1,-1):
      self.seg[i] = self.segfunc(self.seg[2*i+1],self.seg[2*i+2])

  def update(self,k,x):
    k += self.n -1
    self.seg[k] = x
    while k:
      k = (k-1)//2
      self.seg[k] = self.segfunc(self.seg[2*k+1],self.seg[2*k+2])

  def query(self,l,r):
    
    l += self.n-1; r += self.n-1
    vl = vr = self.ide
    while l < r:
      if l & 1 == 0:
        vl = self.segfunc(vl,self.seg[l])
        l += 1
      if r & 1 == 0:
        vr = self.segfunc(vr,self.seg[r-1])
      l = (l-1)//2; r = (r-1)//2
    return self.segfunc(vl,vr)

  def query1(self,l,r):
    
    l += self.n-1; r += self.n-1
    res = self.ide
    while l < r:
      if l & 1 == 0:
        res = self.segfunc(res,self.seg[l])
        l += 1
      if r & 1 == 0:
        res = self.segfunc(res,self.seg[r-1])
      l = (l-1)//2; r = (r-1)//2
    return res

  def query2(self, p, q):
      if q <= p:
          return self.ide
      p += self.n - 1
      q += self.n - 2
      res = self.ide
      while q - p > 1:
          if p & 1 == 0:
              res = self.segfunc(res, self.seg[p])
          if q & 1 == 1:
              res = self.segfunc(res, self.seg[q])
              q -= 1
          p = p // 2
          q = (q - 1) // 2 
      if p == q:
          res = self.segfunc(res, self.seg[p])
      else:
          res = self.segfunc(self.segfunc(res, self.seg[p]), self.seg[q])
      return res
    

def segor(a,b):
  return a|b

n = int(input())
st = SegmentTree(n,segor,0)
S = input()
data = [0] * n
for i,si in enumerate(S):
  k = ord(si)-ord("a")
  data[i] = 1 << k
st.apply(data)
Q = int(input())
for _ in range(Q):
  typo,a,b = input().split()
  if typo == "1":
    st.update(int(a)-1,1 << (ord(b)-ord("a")))
  if typo == "2":
    print(bin((st.query1(int(a)-1,int(b))))[2:].count("1"))

Solution (Python):

import sys, math, itertools, collections, bisect
input = lambda: sys.stdin.buffer.readline().rstrip().decode('utf-8')
inf = float('inf') ;mod = 10**9+7
mans = inf ;ans = 0 ;count = 0 ;pro = 1

class SegmentTree:
  __slots__ = ['ide','n','seg','segfunc']

  def __init__(self,size,func,element):
    self.segfunc = func
    self.ide = element
    
    self.n = 2 ** (n-1).bit_length()
    
    
    self.seg = [self.ide] * (2*self.n-1)

  def apply(self,array):
    arraysize = len(array)
    
    for i in range(arraysize):
      self.seg[self.n-1+i] = array[i]
    
    for i in range(self.n-2,-1,-1):
      self.seg[i] = self.segfunc(self.seg[2*i+1],self.seg[2*i+2])

  def update(self,k,x):
    k += self.n -1
    self.seg[k] = x
    while k:
      k = (k-1)//2
      self.seg[k] = self.segfunc(self.seg[2*k+1],self.seg[2*k+2])

  def query(self,l,r):
    
    l += self.n-1; r += self.n-1
    vl = vr = self.ide
    while l < r:
      if l & 1 == 0:
        vl = self.segfunc(vl,self.seg[l])
        l += 1
      if r & 1 == 0:
        vr = self.segfunc(vr,self.seg[r-1])
      l = (l-1)//2; r = (r-1)//2
    return self.segfunc(vl,vr)

  def query2(self, p, q):
      if q <= p:
          return self.ide
      p += self.n - 1
      q += self.n - 2
      res = self.ide
      while q - p > 1:
          if p & 1 == 0:
              res = self.segfunc(res, self.seg[p])
          if q & 1 == 1:
              res = self.segfunc(res, self.seg[q])
              q -= 1
          p = p // 2
          q = (q - 1) // 2 
      if p == q:
          res = self.segfunc(res, self.seg[p])
      else:
          res = self.segfunc(self.segfunc(res, self.seg[p]), self.seg[q])
      return res
    

def segor(a,b):
  return a|b

n = int(input())
st = SegmentTree(n,segor,0)
S = input()
data = [0] * n
for i,si in enumerate(S):
  k = ord(si)-ord("a")
  data[i] = 1 << k
st.apply(data)
Q = int(input())
for _ in range(Q):
  typo,a,b = input().split()
  if typo == "1":
    st.update(int(a)-1,1 << (ord(b)-ord("a")))
  if typo == "2":
    print(bin((st.query2(int(a)-1,int(b))))[2:].count("1"))

Solution (Python):

import sys, math, itertools, collections, bisect
input = lambda: sys.stdin.buffer.readline().rstrip().decode('utf-8')
inf = float('inf') ;mod = 10**9+7
mans = inf ;ans = 0 ;count = 0 ;pro = 1

class SegmentTree:
  __slots__ = ['ide','n','seg','segfunc']

  def __init__(self,size,func,element):
    self.segfunc = func
    self.ide = element
    
    self.n = 2 ** (n-1).bit_length()
    
    
    self.seg = [self.ide] * (2*self.n-1)

  def apply(self,array):
    arraysize = len(array)
    
    for i in range(arraysize):
      self.seg[self.n-1+i] = array[i]
    
    for i in range(self.n-2,-1,-1):
      self.seg[i] = self.segfunc(self.seg[2*i+1],self.seg[2*i+2])

  def update(self,k,x):
    k += self.n -1
    self.seg[k] = x
    while k:
      k = (k-1)//2
      self.seg[k] = self.segfunc(self.seg[2*k+1],self.seg[2*k+2])

  def query(self,l,r):
    
    l += self.n-1; r += self.n-1
    vl = vr = self.ide
    while l < r:
      if l & 1 == 0:
        vl = self.segfunc(vl,self.seg[l])
        l += 1
      if r & 1 == 0:
        vr = self.segfunc(vr,self.seg[r-1])
      l = (l-1)//2; r = (r-1)//2
    return self.segfunc(vl,vr)

def segor(a,b):
  return a|b

n = int(input())
st = SegmentTree(n,segor,0)
S = input()
data = [0] * n
for i,si in enumerate(S):
  k = ord(si)-ord("a")
  data[i] = 1 << k
st.apply(data)
Q = int(input())
for _ in range(Q):
  typo,a,b = input().split()
  if typo == "1":
    st.update(int(a)-1,1 << (ord(b)-ord("a")))
  if typo == "2":
    print(bin((st.query(int(a)-1,int(b))))[2:].count("1"))

Solution (Python):

import sys, math, itertools, collections, bisect
input = lambda: sys.stdin.buffer.readline().rstrip().decode('utf-8')
inf = float('inf') ;mod = 10**9+7
mans = inf ;ans = 0 ;count = 0 ;pro = 1

class SegmentTree:
  __slots__ = ['ide','n','seg','segfunc']

  def __init__(self,size,func,element):
    self.segfunc = func
    self.ide = element
    
    self.n = 2 ** (n-1).bit_length()
    
    
    self.seg = [self.ide] * (2*self.n-1)

  def apply(self,array):
    arraysize = len(array)
    
    for i in range(arraysize):
      self.seg[self.n-1+i] = array[i]
    
    for i in range(self.n-2,-1,-1):
      self.seg[i] = self.segfunc(self.seg[2*i+1],self.seg[2*i+2])

  def update(self,k,x):
    k += self.n -1
    self.seg[k] = x
    while k:
      k = (k-1)//2
      self.seg[k] = self.segfunc(self.seg[2*k+1],self.seg[2*k+2])

  def notrec(self,l,r):
    
    l += self.n-1; r += self.n-1
    vl = vr = self.ide
    while l < r:
      if l & 1 == 0:
        vl = self.segfunc(vl,self.seg[l])
        l += 1
      if r & 1 == 0:
        vr = self.segfunc(vr,self.seg[r-1])
      l = (l-1)//2; r = (r-1)//2
    return self.segfunc(vl,vr)

def makebin(s):
  k = ord(s)-ord("a")
  
  return 1 << k

def segfunc(a,b):
  return a | b

def out(n):
  count = 0
  while n:
    if n & 1 == 1:
      print(chr(ord("a")+count))
    n//=2
    count += 1

n = int(input())
st = SegmentTree(n,segfunc,0)
S = input()
for i,si in enumerate(S):
  st.update(i,makebin(si))
Q = int(input())


for _ in range(Q):
  typo,a,b = input().split()
  if typo == "1":
    st.update(int(a)-1,makebin(b))
  else:
    print(bin(st.notrec(int(a)-1,int(b)))[1:].count("1"))

Solution (Python):
class SegmentTree:

    def __init__(self, ls, ide, seg_func):
        n = len(ls)
        self.num = 2 ** (n - 1).bit_length()
        self.seg_func = seg_func
        self.ide = ide
        self.tree = [self.ide] * (2 * self.num - 1)
        for i, l in enumerate(ls):
            self.tree[i + self.num - 1] = l

        for i in range(self.num - 2, -1, -1):  
            self.tree[i] = seg_func(self.tree[2 * i + 1], self.tree[2 * i + 2])

    def update(self, i, x):
        i += self.num - 1
        self.tree[i] = x
        while i:
            i = (i-1)//2
            self.tree[i] = self.seg_func(self.tree[2 * i + 1], self.tree[2 * i + 2])

    def query(self, l, r):
        if r < l:
            return ValueError('invalid index')

        l += self.num - 1
        r += self.num - 2
        res = self.ide
        while r - l > 1:  
            if l & 1 == 0:
                res = self.seg_func(res, self.tree[l])
            if r & 1 == 1:
                res = self.seg_func(res, self.tree[r])
                r -= 1
            l = l // 2  
            r = (r - 1) // 2  
        if l == r:
            res = self.seg_func(res, self.tree[l])
        else:
            res = self.seg_func(res, self.tree[l])
            res = self.seg_func(res, self.tree[r])
        return res


def f(a, b):
    return a | b


n = int(input())
s = [1 << (ord(r) - ord("a")) for r in input()]
q = int(input())
st = SegmentTree(s, 0, f)

for _ in range(q):
    m, i, c = input().split()

    if int(m) - 1:
        x = st.query(int(i)-1, int(c))
        print(bin(x).count("1"))
    else:
        st.update(int(i)-1, 1 << (ord(c) - ord("a")))

Solution (Python):
def i1():
 return int(input())
def i2():
 return [int(i) for i in input().split()]
import sys
sys.setrecursionlimit(10**6)

n=i1()
s=input()
q=i1()
N=0
while n:
  n>>=1
  N+=1
n=2**N

t=[0 for i in range(2*n-1)]

def ud(i,x):
  i+=n-1
  t[i]=x
  while i:
    i=(i-1)//2
    t[i]=t[i*2+1] | t[i*2+2]

def qr(a,b,k,l,r):
  
  if r<=a or b<=l:
     return 0
  elif a<=l and r<=b:
     
     return t[k]
  else:
     return qr(a,b,k*2+1,l,(l+r)//2) | qr(a,b,k*2+2,(l+r)//2,r)

for i in range(len(s)):
  ud(i,1<<(ord(s[i])-ord("a")))

while q:
 [ty,i,c]=[i for i in input().split()]
 ty=int(ty)
 i=int(i)
 if ty==1:
   ud(i-1,1<<(ord(c)-ord("a")))
 else:
   c=int(c)
   x=0
   z=qr(i-1,c,0,0,n)
   while z:
     if z%2==1:
        x+=1
     z>>=1
   print(x)
 q-=1

Solution (Python):
import sys
input = sys.stdin.readline
n = int(input())

ss = list(input())
s = []
for i in range(n):
    s.append(1<<(ord(ss[i])-97))


def segfunc(x,y):
    
    return x | y

def init(init_val):
    
    for i in range(n):
        seg[i+num-1]=init_val[i]
    
    for i in range(num-2,-1,-1) :
        seg[i]=segfunc(seg[2*i+1],seg[2*i+2]) 
    
def update(k,x):
    k += num-1
    seg[k] = x
    while k:
        k = (k-1)//2
        seg[k] = segfunc(seg[k*2+1],seg[k*2+2])
    
def query(p,q,k,l,r):
    if r<=p or q<=l:
        return ide_ele
    if p<=l and r<=q:
        return seg[k]
    else:
        vl = query(p,q,k*2+1,l,(r+l)//2)
        vr = query(p,q,k*2+2,(l+r)//2,r)
        return segfunc(vl,vr)


ide_ele = 0


num =2**(n-1).bit_length()
seg=[ide_ele]*2*num
init(s)


def popcnt(n):
    c = (n & 0x5555555555555555) + ((n>>1) & 0x5555555555555555)
    c = (c & 0x3333333333333333) + ((c>>2) & 0x3333333333333333)
    c = (c & 0x0f0f0f0f0f0f0f0f) + ((c>>4) & 0x0f0f0f0f0f0f0f0f)
    c = (c & 0x00ff00ff00ff00ff) + ((c>>8) & 0x00ff00ff00ff00ff)
    c = (c & 0x0000ffff0000ffff) + ((c>>16) & 0x0000ffff0000ffff)
    c = (c & 0x00000000ffffffff) + ((c>>32) & 0x00000000ffffffff)
    return c

q = int(input())

for i in range(q):
    qq,xx,yy = map(str,input().split())
    if qq == '1':
        xx = int(xx)
        update(xx-1,1<<(ord(yy)-97))
    else:
        xx,yy = int(xx),int(yy)
        res = query(xx-1,yy,0,0,num)
        print(popcnt(res))

Solution (Python):
import sys
input = sys.stdin.readline
n = int(input())

ss = list(input())
s = []
for i in range(n):
    s.append(1<<(ord(ss[i])-97))


def segfunc(x,y):
    
    return x | y

def init(init_val):
    
    for i in range(n):
        seg[i+num-1]=init_val[i]
    
    for i in range(num-2,-1,-1) :
        seg[i]=segfunc(seg[2*i+1],seg[2*i+2]) 
    
def update(k,x):
    k += num-1
    seg[k] = x
    while k:
        k = (k-1)//2
        seg[k] = segfunc(seg[k*2+1],seg[k*2+2])
    
def query(p,q,k,l,r):
    if r<=p or q<=l:
        return ide_ele
    if p<=l and r<=q:
        return seg[k]
    else:
        vl = query(p,q,k*2+1,l,(r+l)//2)
        vr = query(p,q,k*2+2,(l+r)//2,r)
        return segfunc(vl,vr)


ide_ele = 0


num =2**(n-1).bit_length()
seg=[ide_ele]*2*num
init(s)


def popcnt(n):
    c = (n & 0x5555555555555555) + ((n>>1) & 0x5555555555555555)
    c = (c & 0x3333333333333333) + ((c>>2) & 0x3333333333333333)
    c = (c & 0x0f0f0f0f0f0f0f0f) + ((c>>4) & 0x0f0f0f0f0f0f0f0f)
    c = (c & 0x00ff00ff00ff00ff) + ((c>>8) & 0x00ff00ff00ff00ff)
    c = (c & 0x0000ffff0000ffff) + ((c>>16) & 0x0000ffff0000ffff)
    c = (c & 0x00000000ffffffff) + ((c>>32) & 0x00000000ffffffff)
    return c

q = int(input())

for i in range(q):
    qq,xx,yy = map(str,input().split())
    if qq == '1':
        xx = int(xx)
        update(xx-1,1<<(ord(yy)-97))
    else:
        xx,yy = int(xx),int(yy)
        res = query(xx-1,yy,0,0,num)
        print(popcnt(res))

Solution (Python):
N = int(input())
S = list(input())
Q = int(input())








MAX_N = 10 ** 6 

data = [0] * (2 * MAX_N - 1) 


def func(vl, vr):
    return (vl | vr)

def init(n_):
    
    n = 1
    while n < n_:
        n *= 2
    return n

n = init(N)

def update(k, a): 
    
    k += n - 1
    data[k] = (1 << a)
    while k > 0: 
        k = (k - 1)//2
        data[k] = func(data[k * 2 + 1], data[k * 2 + 2])

def query(a, b, k = 0, l = 0, r = n):
    if r <= a or b <= l:
        return 0
    if a <= l and r <= b:
        return data[k]
    else:
        vl = query(a, b, k * 2 + 1, l, (l + r)//2)
        vr = query(a, b, k * 2 + 2, (l + r)//2, r)
        return func(vl, vr)

def initialize(A): 
    for i, a in enumerate(A):
        data[i + n - 1] = (1 << (ord(a) - 97))
        
    for i in range((2 * n - 3)//2, -1, -1):
        data[i] = func(data[i * 2 + 1], data[i * 2 + 2])








initialize(S)





for _ in range(Q):
    a, b, c = map(str, input().split())
    if a == '1':
        update(int(b) - 1, (ord(c) - 97))
    else:
        tmp = query(int(b) - 1, int(c))
        count = 0
        for j in range(26):
            if (tmp >> j) & 1 == 1:
                count += 1
        
        print (count)

Solution (Python):
N = int(input())
S = list(input())
Q = int(input())








MAX_N = 10 ** 6 

data = [0] * (2 * MAX_N - 1) 


def func(vl, vr):
    return (vl | vr)

def init(n_):
    
    n = 1
    while n < n_:
        n *= 2
    return n

n = init(N)

def update(k, a): 
    
    k += n - 1
    data[k] = (1 << a)
    while k > 0: 
        k = (k - 1)//2
        data[k] = func(data[k * 2 + 1], data[k * 2 + 2])

def query(a, b, k = 0, l = 0, r = n):
    if r <= a or b <= l:
        return 0
    if a <= l and r <= b:
        return data[k]
    else:
        vl = query(a, b, k * 2 + 1, l, (l + r)//2)
        vr = query(a, b, k * 2 + 2, (l + r)//2, r)
        return func(vl, vr)

def initialize(A): 
    for i, a in enumerate(A):
        data[i + n - 1] = (1 << (ord(a) - 97))
        
    for i in range((2 * n - 3)//2, -1, -1):
        data[i] = func(data[i * 2 + 1], data[i * 2 + 2])








initialize(S)





for _ in range(Q):
    a, b, c = map(str, input().split())
    if a == '1':
        update(int(b) - 1, (ord(c) - 97))
    else:
        tmp = query(int(b) - 1, int(c))
        count = 0
        for j in range(26):
            if (tmp >> j) & 1 == 1:
                count += 1
        
        print (count)

Solution (Python):


class SegmentTree:
  arr=None
  tree=None
  n=0
  
  DEF=0

  def __init__(self,arr):
    self.arr=arr
    size=len(arr)
    
    self.n=1
    while self.n<size:
      self.n*=2
    self.tree=[self.DEF]*(2*self.n-1)
    
    
    
    for i in range(size):
      self.tree[i+self.n-1]=arr[i]
    for i in range(self.n-2,-1,-1):
      self.tree[i]=self.__choose__(self.tree[2*i+1],self.tree[2*i+2])
    
    
  
  def __choose__(self,a,b):
    return a | b
  
  
  def update(self,x,val):
    x+=self.n-1
    self.tree[x]=val
    while x>0:
      x=(x-1)//2
      self.tree[x]=self.__choose__(self.tree[2*x+1],self.tree[2*x+2])
      
  
  
  
  def get_val(self,a,b,k=0,l=0,r=-1):
    
    if r<0:
      r=self.n
      
    
    if r<=a or b<=l:
      return self.DEF
    
    
    if a<=l and r<=b:
      return self.tree[k]
    
    
    ll=self.get_val(a,b,2*k+1,l,(l+r)//2)
    rr=self.get_val(a,b,2*k+2,(l+r)//2,r)
    
    return self.__choose__(ll,rr)
    
  def show(self):
    print("----")
    print(list(map(bin,self.tree)))
    print(self.tree)
    
base=ord("a")
ALPHA="abcdefghijklmnopqrstuvwxyz"
def change_alpha_to_num(c):
  if c not in ALPHA:
    return 0
  return 1<<(ord(c)-base)

import sys
readline=sys.stdin.readline

N=int(readline())
S=readline()
Sarr=list(map(change_alpha_to_num,list(S)))
ST=SegmentTree(Sarr)
Q=int(readline())
for i in range(Q):
  q=list(readline().split())
  if q[0]=="1":
    i,c=int(q[1])-1,q[2]
    ST.update(i,change_alpha_to_num(c))
  elif q[0]=="2":
    l,r=int(q[1])-1,int(q[2])-1
    print(bin(ST.get_val(l,r+1)).count("1"))