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):
class BIT:
    """
    https://tjkendev.github.io/procon-library/python/range_query/bit.html
    Binary index treeの実装
    配列[a1, a2,...,an]に対して以下のクエリをO(logn)で行う:
        1. aiにxを加える
        2. 区間和 ai + a(i+1) + ... + aj の和を求める
    """
    def __init__(self, n):
        """
        添字は1スタート
        """
        self.n = n
        self.data = [0] * (n + 1)
        self.el = [0] * (n + 1)

    def add(self, i, x):
        """
        i>0に対してaiにxを加算(x < 0でもOK)
        """
        if i <= 0 or self.n < i:
            print("i should be within 1 to n")
        else:
            self.el[i] += x
            while i <= self.n:
                self.data[i] += x
                i += i & -i

    def sum(self, i):
        """
        添字1からiまでの累積和を求める
        """
        s = 0
        while i > 0:
            s += self.data[i]
            i -= i & -i
        return s

    def get(self, i, j=None):
        """
        添字iからjまでの累積和を求める
        j=Noneの場合はaiの値を返す
        """
        if j is None:
            return self.el[i]
        return self.sum(j) - self.sum(i - 1)


"""
ここから本問の解答
各アルファベットごとにBITを作成する
"""

N = int(input())
S = list(input())
Q = int(input())



Alphabet = [None] * 26
for i in range(26):
    Alphabet[i] = BIT(N)


for i, s in enumerate(S):
    num = ord(s) - 97
    Alphabet[num].add(i + 1, 1)

"""
各クエリごとに行う操作を関数にまとめておく
"""
def change(i, c):
    if S[i - 1] != c:
        pre = ord(S[i - 1]) - 97
        Alphabet[pre].add(i, -1)
        post = ord(c) - 97
        Alphabet[post].add(i, 1)
        S[i - 1] = c

def appear(l, r):
    char = 0
    for i in range(26):
        if Alphabet[i].get(l, r) >= 1:
            char += 1
    return char

"""
クエリ処理
"""

for _ in range(Q):
    flag, x, y = input().split()
    if flag == "1":
        i, c = int(x), y
        change(i, c)
    elif flag == "2":
        l, r = int(x), int(y)
        print(appear(l, r))

Solution (Python):
from sys import stdin
import sys

import collections
from functools import cmp_to_key
import heapq


def rsa(sep = ''):
    if sep == '' :
        return input().split() 
    else: return input().split(sep)
def rip(sep = ''):
    if sep == '' :
        return map(int, input().split()) 
    else: return map(int, input().split(sep))
def ria(sep = ''): 
    return list(rip(sep))
def ri(): return int(input())
def rd(): return float(input())
def rs(): return input()


class fenwick_tree:
    def __init__(self, n):
        self.N = n
        self.n = 1 
        while(self.n < self.N):
            self.n *= 2
        self.data = [0] * (self.n + 1)

    def add(self, idx, x):
        while idx <= self.n:
            self.data[idx] += x
            idx += (idx & -idx)

    def cumulate(self, idx):
        s = 0
        while idx > 0:
            s += self.data[idx]
            idx -= (idx & -idx)
        return s

def main():
    N = ri()
    S = rs()
    Q = ri()
    ans = []

    bit = [fenwick_tree(N) for i in range(26)]
    for i in range(N):
        d = ord(S[i]) - ord('a')
        bit[d].add(i + 1, 1)

    ca = [c for c in S]
    for _ in range(Q):
        ss = rsa()
        if ss[0] == '1':
            pos = int(ss[1]) - 1
            c = ss[2][0]
            bit[ord(ca[pos]) - ord('a')].add(pos + 1, -1)
            ca[pos] = c
            bit[ord(ca[pos]) - ord('a')].add(pos + 1, +1)
        else:
            l = int(ss[1]) - 1
            r = int(ss[2]) - 1
            cnt = 0
            for i in range(26):
                su = bit[i].cumulate(r + 1) - bit[i].cumulate(l)
                if su > 0: cnt += 1
            ans.append(cnt)
    
    print("\n".join([str(n) for n in ans]))


if __name__ == "__main__":
    main()

Solution (Python):
import sys
sys.setrecursionlimit(10 ** 6)
input = sys.stdin.readline
N = int(input())
S = input().strip()
Q = int(input())
n = 1
while n < N:
    n *= 2
T = [0] * (2 * n)

def update(k, a):
    k += n-1
    T[k] = 1 << ord(a) - 97
    while k > 0:
        k = (k - 1) // 2
        T[k] = T[k*2+1] | T[k*2+2]

def query(a, b, k, l, r):
    
    if r <= a or b <= l:
        
        return 0
    if a <= l and r <= b:
        
        return T[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 vl | vr

for i in range(N):
    update(i, S[i])

for q in range(Q):
    f, i, c = [x for x in input().strip().split()]
    if f == '1':
        
        update(int(i)-1, c)
    elif f == '2':
        
        tmp = query(int(i)-1, int(c), 0, 0, n)
        ans = 0
        for i in range(26):
            ans += tmp >> i & 1
         
        print(ans)

Solution (Python):
from collections import defaultdict

class BIT(object):
    def __init__(self, N, init=0):
        self.N = N
        self.bit = [init for _ in range(N)]

    def add(self, k, w):
        x = k
        while x < self.N:
            self.bit[x] += w
            x |= x + 1

    def sum(self, k):
        s = 0
        x = k - 1
        while x >= 0:
            s += self.bit[x]
            x = (x & (x + 1)) - 1
        return s

n = int(input())
s = list(input())
q = int(input())

d = defaultdict(lambda: BIT(n))
for i, si in enumerate(s):
    d[si].add(i, 1)

for i in range(q):
    k, x, y = input().split()
    if k == '1':
        x = int(x) - 1
        d[s[x]].add(x, -1)
        d[y].add(x, 1)
        s[x] = y
    else:
        l = int(x) - 1
        r = int(y) - 1
        ans = 0
        for v in d.values():
            ans += (v.sum(r + 1) - v.sum(l)) > 0
        print(ans)

Solution (Python):

import sys
import math

def solve(N, S, Q, queries):
    def update(i, c):
        values[i] = c
        s = (i // sN) * sN
        buckets[i//sN] = 0
        for v in values[s:min(s+sN, len(values))]:
            buckets[i//sN] |= 1 << v

    def count(l, r):
        res = 0
        for i in range(sN):
            ll = i * sN
            rr = ll + sN
            if r <= ll or rr <= l:
                continue
            if l <= ll and rr <= r:
                res |= buckets[i]
            else:
                for j in range(max(l, ll), min(r, rr)):
                    res |= 1 << values[j]
        return sum(b == '1' for b in bin(res))
        
    sN = math.ceil(N ** 0.5)
    values = [ord(c)-ord('a') for c in S]
    buckets = [0] * sN
    for i, v in enumerate(values):
        buckets[i//sN] |= 1 << v
    for t, x, y in queries:
        if t == 1:
            update(int(x)-1, ord(y)-ord('a'))
        else:
            yield count(int(x)-1, int(y))


def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))
    S = next(tokens)
    Q = int(next(tokens))
    queries = [(int(next(tokens)), next(tokens), next(tokens)) for _ in range(Q)]
    for result in solve(N, S, Q, queries):
        print(result)

if __name__ == '__main__':
    main()

Solution (Python):

import sys
sys.setrecursionlimit(10**9)
INF=10**18
MOD=10**9+7
def input(): return sys.stdin.readline().rstrip()

def main():
    class SegmentTree:
        def __init__(self,n,ide_ele,segfunc):
            self.ide_ele=ide_ele
            self.segfunc=segfunc
            self.num=2**(n-1).bit_length()
            self.dat=[ide_ele]*2*self.num
        
        def init(self,iter):
            for i in range(n):
                self.dat[i+self.num]=iter[i]
            for i in range(self.num-1,0,-1):
                self.dat[i]=self.segfunc(self.dat[i*2],self.dat[i*2+1])
        
        def update(self,k,x):
            k+=self.num
            self.dat[k]=x
            while k:
                k//=2
                self.dat[k]=self.segfunc(self.dat[k*2],self.dat[k*2+1])
        
        def query(self,p,q):
            if q<=p:
                return self.ide_ele
            p+=self.num
            q+=self.num-1
            res=self.ide_ele
            while q-p>1:
                if p&1==1:
                    res=self.segfunc(res,self.dat[p])
                if q&1==0:
                    res=self.segfunc(res,self.dat[q])
                    q-=1
                p=(p+1)//2
                q=q//2
            if p==q:
                res=self.segfunc(res,self.dat[p])
            else:
                res=self.segfunc(self.segfunc(res,self.dat[p]),self.dat[q])
            return res
    
    N=int(input())
    S=list(input())
    Q=int(input())
    seg=[SegmentTree(N,0,lambda x,y:x+y) for _ in range(26)]
    
    S2=[0]*N
    
    for i in range(N):
        S2[i]=ord(S[i])-ord('a')
    
    for i,x in enumerate(S2):
        p=seg[x].query(i,i+1)
        seg[x].update(i,p+1)
    
    for _ in range(Q):
        a,b,c=input().split()
        if a=='1':
            b=int(b)-1
            c=ord(c)-ord('a')
            p=seg[c].query(b,b+1)
            seg[c].update(b,p+1)
            q=seg[S2[b]].query(b,b+1)
            seg[S2[b]].update(b,q-1)
            S2[b]=c
        else:
            b=int(b)-1
            c=int(c)-1
            ans=0
            for i in range(26):
                ans+=bool(seg[i].query(b,c+1))
            print(ans)

if __name__ == '__main__':
    main()

Solution (Python):
import sys
from bisect import bisect_left,bisect_right,insort


def main():
    n=int(input())
    s=list(str(input()))
    p=[[] for _ in range(26)]
    for i,S in enumerate(s):
        p[ord(S)-ord('a')].append(i)
    q=int(input())
    for i in range(q):
        a,b,c=map(str,input().split())
        if a=='1':
            b=int(b)-1
            if s[b]==c:
                continue
            else:
                insl=bisect_left(p[ord(s[b])-ord('a')],b)
                p[ord(s[b])-ord('a')].pop(insl)
                insort(p[ord(c)-ord('a')],b)
                s[b]=c
        else:
            b,c=int(b)-1,int(c)-1
            cnt=0
            for i in range(26):
                insl=bisect_left(p[i],b)
                if insl>=len(p[i]):
                    continue
                elif p[i][insl]<=c:
                    cnt+=1
            print(cnt)

if __name__ == '__main__':
    main()

Solution (Python):
from collections import defaultdict
import bisect

alphabet="abcdefghijklmnopqrstuvwxyz"

bS = int(input())
S= input()
nQ = int(input())

S = [i for i in S]

query = []
for i in range(nQ):
  query.append(input().split())

locs =defaultdict(list)

for i,char in enumerate(S):
    locs[char].append(i)
    
def countChars(iter,ss,ee):
  nChar = 0
  for i in alphabet:
    if len(locs[i]) == 0:
      pass
    else:
      sptr = bisect.bisect_right(locs[i],ss)
      eptr = bisect.bisect_left(locs[i],ee)
      if sptr == eptr:
        if sptr < 1 or sptr > len(locs[i]):
          continue
        else:
          if locs[i][sptr-1] == ss:
            nChar+=1
      else:
        nChar += 1
  return nChar
    
  
res = []
for iter,iQ in enumerate(query):
  if int(iQ[0]) == 2:
    res.append(str( countChars(iter,int(iQ[1])-1,int(iQ[2])) ))
  if int(iQ[0]) == 1:
    location = int(iQ[1])-1
    curChar  = S[location]
    if curChar != iQ[2]:
      locs[curChar].remove(location) 
      bisect.insort(locs[iQ[2]],location)
      S[location] = iQ[2]
      
print(" ".join(res))

Solution (Python):
from collections import defaultdict, deque, Counter
from heapq import heappush, heappop, heapify
import math
import bisect
import random
from itertools import permutations, accumulate, combinations, product
import sys
import string
from bisect import bisect_left, bisect_right
from math import factorial, ceil, floor
from operator import mul
from functools import reduce
import pprint
sys.setrecursionlimit(10 ** 9)

INF = 10 ** 20
def LI(): return list(map(int, sys.stdin.buffer.readline().split()))
def I(): return int(sys.stdin.buffer.readline())
def LS(): return sys.stdin.buffer.readline().rstrip().decode('utf-8').split()
def S(): return sys.stdin.buffer.readline().rstrip().decode('utf-8')
def IR(n): return [I() for i in range(n)]
def LIR(n): return [LI() for i in range(n)]
def SR(n): return [S() for i in range(n)]
def LSR(n): return [LS() for i in range(n)]
def SRL(n): return [list(S()) for i in range(n)]
def MSRL(n): return [[int(j) for j in list(S())] for i in range(n)]
mod = 1000000007

class BIT:
    def __init__(self, size):
        self.bit = [0] * size
        self.size = size
        self.total = 0

    def add(self, i, w):
        x = i + 1
        self.total += w
        while x <= self.size:
            self.bit[x - 1] += w
            x += x & -x
        return

    def sum(self, i):
        res = 0
        x = i + 1
        while x:
            res += self.bit[x - 1]
            x -= x & -x
        return res

    def interval_sum(self, i, j): 
        return self.sum(j - 1) - self.sum(i - 1) if i else self.sum(j - 1)

def main():
    N = I()
    s = list(S())
    Q = I()
    D = defaultdict(lambda : BIT(N))
    for i in range(N):
        D[s[i]].add(i,1)
    for j in range(Q):
        qi,i,c = LS()
        if qi == "1":
            i = int(i) - 1
            D[s[i]].add(i,-1)
            D[c].add(i,1)
            s[i] = c
        else:
            l,r = int(i)-1, int(c)
            result = 0
            for k in range(97,123):
                if D[chr(k)].interval_sum(l,r):
                    result += 1
            print(result)

if __name__ == '__main__':
    main()

Solution (Python):
n = int(input())
s = input()
q = int(input())
commands = []
for _ in range(q):
    com, x, y = input().split()
    commands.append((com, int(x), y))

size = 1
while size < n:
    size *= 2


segment_tree = [0 for _ in range(2 * size - 1)]


def alphabet2bit(string):
    return 1 << (ord(string) - ord('a'))

def update(i, x, segment_tree):
    i += size - 1
    segment_tree[i] = alphabet2bit(x)
    while i > 0:
        i = (i - 1) // 2
        left = segment_tree[i * 2 + 1]
        right = segment_tree[i * 2 + 2]
        segment_tree[i] = left | right

def getSum(s, t, k, l, r, segment_tree):
    if r <= s or t <= l:
        return 0
    if s <= l and r <= t:
        return segment_tree[k]
    else:
        ask_left = getSum(s, t, k * 2 + 1, l, (l + r) // 2, segment_tree)
        ask_right = getSum(s, t, k * 2 + 2, (l + r) // 2, r, segment_tree)
        return ask_left | ask_right

for i in range(n):
    update(i, s[i], segment_tree)

for com, x, y in commands:
    if com == '1':
        update(x - 1, y, segment_tree)
    else:
        result = getSum(x - 1, int(y), 0, 0, size, segment_tree)
        print(bin(result).count('1'))

Solution (Python):




class SegTree:
    
    
    
    
        
    def __init__(self, n, init_list ,segfunc, ide_ele):
        
        
        self.num = 2**((n-1).bit_length())
        self.seg = [ide_ele]*(2*self.num)
        self.segfunc = segfunc
        self.ide_ele = ide_ele
        
        for i in range(n):
            self.seg[i+self.num-1] = init_list[i]        
        
        for i in range(self.num-2, -1, -1):
            self.seg[i] = 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, l,r):
        if r<=l:
            return self.ide_ele
        
        l += self.num-1 
        r += self.num-2 
        ret = self.ide_ele
        
        while r-l>1:
            if l&1 == 0:
                ret = self.segfunc(ret,self.seg[l])
            
            if r&1 == 1:
                ret = self.segfunc(ret,self.seg[r])
                r -= 1
            
            l = l//2
            r = (r-1)//2
        if r==l:
            ret = self.segfunc(ret, self.seg[r])
        else:
            ret = self.segfunc(ret, self.seg[l])
            ret = self.segfunc(ret, self.seg[r])
        
        return ret
            
def segfunc(x,y):
    return max(x,y)

N = int(input())
S = list(input())
Q = int(input())

alphalist = [[0]*N for _ in range(26)]
atmp = ord('a')
for i,s in enumerate(S):
    alphalist[ord(s)-atmp][i] = 1

seglist = [None]*26
for i in range(26):
    seglist[i] = SegTree(N,alphalist[i],segfunc,0)

ans = []
for i in range(Q):
    t,l,r = map(str,input().split())
    if t=='1':
        i = int(l)-1
        c = r
        
        org_idx = ord(S[i])-atmp
        seglist[org_idx].update(i,0)
        S[i] = c
        upt_idx = ord(c) - atmp
        seglist[upt_idx].update(i,1)
                
        
    else:
        l,r = int(l)-1,int(r)
        cnt = 0
        for i in range(26):
            cnt += seglist[i].query(l,r)
        ans.append(cnt)

for a in ans:
    print(a)

Solution (Python):
from collections import defaultdict, deque, Counter
from heapq import heappush, heappop, heapify
import math
import bisect
import random
from itertools import permutations, accumulate, combinations, product
import sys
import string
from bisect import bisect_left, bisect_right
from math import factorial, ceil, floor
from operator import mul
from functools import reduce
import pprint
sys.setrecursionlimit(10 ** 9)


INF = 10 ** 20
def LI(): return list(map(int, sys.stdin.buffer.readline().split()))
def I(): return int(sys.stdin.buffer.readline())
def LS(): return sys.stdin.buffer.readline().rstrip().decode('utf-8').split()
def S(): return sys.stdin.buffer.readline().rstrip().decode('utf-8')
def IR(n): return [I() for i in range(n)]
def LIR(n): return [LI() for i in range(n)]
def SR(n): return [S() for i in range(n)]
def LSR(n): return [LS() for i in range(n)]
def SRL(n): return [list(S()) for i in range(n)]
def MSRL(n): return [[int(j) for j in list(S())] for i in range(n)]
mod = 1000000007


class BIT:
    def __init__(self, size):
        self.bit = [0] * size
        self.size = size
        self.total = 0

    def add(self, i, w):
        x = i + 1
        self.total += w
        while x <= self.size:
            self.bit[x - 1] += w
            x += x & -x
        return

    def sum(self, i):
        res = 0
        x = i + 1
        while x:
            res += self.bit[x - 1]
            x -= x & -x
        return res

    def interval_sum(self, i, j): 
        return self.sum(j - 1) - self.sum(i - 1) if i else self.sum(j - 1)

n = I()
s = list(S())
D = defaultdict(lambda:BIT(n))
for i in range(n):
    D[s[i]].add(i, 1)

q = I()
for j in range(q):
    qi, i, c = LS()
    if qi == '1':
        i = int(i) - 1
        D[s[i]].add(i, -1)
        D[c].add(i, 1)
        s[i] = c
    else:
        l, r = int(i) - 1, int(c)
        ret = 0
        for k in range(97, 123):
            if D[chr(k)].interval_sum(l, r):
                ret += 1
        print(ret)

Solution (Python):

N = int(input())
S = list(input())
BITS = [[0]*(N+1) for _ in range(26)]




def ctoi(alphabet):
    return ord(alphabet)-97



def BIT_query(idx):
    res = [0]*26
    for i in range(26):
        p = idx
        tmp = 0
        while p > 0:
            tmp += BITS[i][p]
            p -= p & (-p)
        res[i] = tmp
    return res


def BIT_update(idx, alphabet, x):  
    while idx <= N:
        BITS[ctoi(alphabet)][idx] += x
        idx += idx&(-idx)



for i in range(N):
    BIT_update(i+1, S[i], 1)


Q = int(input())
for _ in range(Q):
    type, a, b = map(str, input().split())
    if type == "1":  
        
        a = int(a)
        if S[a-1] == b:
            continue
        BIT_update(a, S[a-1], -1)  
        BIT_update(a, b, 1)  
        S[a-1] = b
    elif type == "2":  
        
        a, b = int(a), int(b)
        cnt1 = BIT_query(a-1)
        cnt2 = BIT_query(b)
        ans = 0
        for i in range(26):
            if cnt2[i] > cnt1[i]:
                ans += 1
        print(ans)

Solution (Python):
from collections import defaultdict, deque, Counter
from heapq import heappush, heappop, heapify
import math
import bisect
import random
from itertools import permutations, accumulate, combinations, product
import sys
import string
from bisect import bisect_left, bisect_right
from math import factorial, ceil, floor
from operator import mul
from functools import reduce
import pprint
sys.setrecursionlimit(10 ** 9)


INF = 10 ** 20
def LI(): return list(map(int, sys.stdin.buffer.readline().split()))
def I(): return int(sys.stdin.buffer.readline())
def LS(): return sys.stdin.buffer.readline().rstrip().decode('utf-8').split()
def S(): return sys.stdin.buffer.readline().rstrip().decode('utf-8')
def IR(n): return [I() for i in range(n)]
def LIR(n): return [LI() for i in range(n)]
def SR(n): return [S() for i in range(n)]
def LSR(n): return [LS() for i in range(n)]
def SRL(n): return [list(S()) for i in range(n)]
def MSRL(n): return [[int(j) for j in list(S())] for i in range(n)]
mod = 1000000007


class BIT:
    def __init__(self, size):
        self.bit = [0] * size
        self.size = size
        self.total = 0

    def add(self, i, w):
        x = i + 1
        self.total += w
        while x <= self.size:
            self.bit[x - 1] += w
            x += x & -x
        return

    def sum(self, i):
        if i < 0:
            return 0
        res = 0
        x = i + 1
        while x:
            res += self.bit[x - 1]
            x -= x & -x
        return res

    def interval_sum(self, i, j): 
        return self.sum(j - 1) - self.sum(i - 1)


n = I()
s = list(S())
D = defaultdict(lambda:BIT(n))
for i in range(n):
    D[ord(s[i])].add(i, 1)

q = I()
for j in range(q):
    qi, i, c = LS()
    i = int(i) - 1
    if qi == '1':
        D[ord(s[i])].add(i, -1)
        D[ord(c)].add(i, 1)
        s[i] = c
    else:
        l, r = i, int(c)
        ret = 0
        for k in range(97, 123):
            if D[k].sum(r - 1) > D[k].sum(l - 1):
                ret += 1
        print(ret)

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

def main():
    N = int(input())
    S = input().rstrip()
    tree = SegmentTree(initial_values=S, f=lambda x,y:x|y, converter=lambda c: 1 << (ord(c)-ord('a')))
    Q = int(input())
    update = tree.update
    query = tree.query
    for _ in range(Q):
        t, a, b = input().rstrip().split()
        if t == '1': update(int(a)-1, b)
        else: print(bin(query(int(a)-1, int(b))).count('1'))

class SegmentTree:
    def __init__(self, n=None, f=max, zero_factory=int, converter=lambda x:x, initial_values=None):
        assert(n or initial_values)
        size = n if n else len(initial_values)
        self.__f, self.__z, self.__c = f, zero_factory, converter
        self.__n = 1 << ((size - 1).bit_length())
        self.__dat = [zero_factory() for _ in range(2 * self.__n)]
        if initial_values:
            zi = self.__get_leaf(0)
            for i, v in enumerate(initial_values): self.__dat[zi + i] = converter(v)
            for i in range(zi-1, -1, -1): self.__dat[i] = f(*self.__get_children(i))

    def update(self, index, value):
        i, v = self.__get_leaf(index), self.__c(value)
        if self.__dat[i] == v: return
        self.__dat[i] = v
        while i:
            i = self.__get_parent(i)
            v = self.__f(*self.__get_children(i))
            if self.__dat[i] == v: break
            self.__dat[i] = v

    def query(self, from_inclusive, to_exclusive):
        ans = self.__z()
        if to_exclusive <= from_inclusive: return ans
        l, r = self.__get_leaf(from_inclusive), self.__get_leaf(to_exclusive) - 1
        while r - l > 1:
            if self.__is_right(l): ans = self.__f(ans, self.__dat[l])
            if self.__is_left(r): ans, r = self.__f(ans, self.__dat[r]), r-1
            l, r = l//2, self.__get_parent(r)
        ans = self.__f(ans, self.__dat[l])
        if l != r: ans = self.__f(ans, self.__dat[r])
        return ans

    def __get_leaf(self, i): return self.__n + i - 1
    def __get_parent(self, i): return (i-1)//2
    def __get_children(self, i): return (self.__dat[2*i+1], self.__dat[2*i+2])
    def __is_left(self, i): return i&1 == 1
    def __is_right(self, i): return i&1 == 0

if __name__ == '__main__':
    main()

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

def main():
    N = int(input())
    S = input().rstrip()
    tree = SegmentTree(initial_values=S, f=lambda x,y:x|y, converter=lambda c: 1 << (ord(c)-ord('a')))
    Q = int(input())
    update = tree.update
    query = tree.query
    for _ in range(Q):
        t, a, b = input().rstrip().split()
        if t == '1': update(int(a)-1, b)
        else: print(bin(query(int(a)-1, int(b))).count('1'))

class SegmentTree:
    def __init__(self, n=None, f=max, zero_factory=int, converter=lambda x:x, initial_values=None):
        assert(n or initial_values)
        size = n if n else len(initial_values)
        self.__f, self.__z, self.__c = f, zero_factory, converter
        self.__n = 1 << ((size - 1).bit_length())
        self.__dat = [zero_factory() for _ in range(2 * self.__n)]
        if initial_values:
            zi = self.__get_leaf(0)
            for i, v in enumerate(initial_values): self.__dat[zi + i] = converter(v)
            for i in range(zi-1, -1, -1): self.__dat[i] = f(*self.__get_children(i))

    def update(self, index, value):
        i, v = self.__get_leaf(index), self.__c(value)
        if self.__dat[i] == v: return
        self.__dat[i] = v
        while i:
            i = self.__get_parent(i)
            self.__dat[i] = self.__f(*self.__get_children(i))

    def query(self, from_inclusive, to_exclusive):
        ans = self.__z()
        if to_exclusive <= from_inclusive: return ans
        l, r = self.__get_leaf(from_inclusive), self.__get_leaf(to_exclusive) - 1
        while r - l > 1:
            if self.__is_right(l): ans = self.__f(ans, self.__dat[l])
            if self.__is_left(r): ans, r = self.__f(ans, self.__dat[r]), r-1
            l, r = l//2, self.__get_parent(r)
        ans = self.__f(ans, self.__dat[l])
        if l != r: ans = self.__f(ans, self.__dat[r])
        return ans

    def __get_leaf(self, i): return self.__n + i - 1
    def __get_parent(self, i): return (i-1)//2
    def __get_children(self, i): return (self.__dat[2*i+1], self.__dat[2*i+2])
    def __is_left(self, i): return i&1 == 1
    def __is_right(self, i): return i&1 == 0

if __name__ == '__main__':
    main()

Solution (Python):
def ctoi(c):  
    return ord(c) - 97


N = int(input())
S = list(input())
bits = [[0]*(N+1) for _ in range(26)]  


def BIT_query(idx):  
    res = [0]*26
    for i in range(26):
        tmp = 0
        p = idx
        while p > 0:  
            tmp += bits[i][p]
            p -= p&(-p)  
        res[i] = tmp
    return res


def BIT_update(idx, alphabet, x):  
    while idx <= N:  
        bits[alphabet][idx] += x
        idx += idx&(-idx)


for i in range(N):  
    BIT_update(i+1, ctoi(S[i]), 1)  

Q = int(input())
for _ in range(Q):
    flag, a, b = map(str, input().split())
    flag = int(flag)
    a = int(a)
    if flag == 1:
        if S[a-1] == b:  
            continue
        else:
            BIT_update(a, ctoi(S[a-1]), -1)  
            BIT_update(a, ctoi(b), 1)  
            S[a-1] = b  
    elif flag == 2:  
        b = int(b)
        cnt1 = BIT_query(b)  
        cnt2 = BIT_query(a-1)  
        ans = 0
        for i in range(26):
            if cnt1[i]-cnt2[i] > 0:  
                ans += 1
        print(ans)

Solution (Python):
import sys
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines

def main():
    N,S,Q,*q = read().split()
    S = S.decode()
    tree = SegmentTree(initial_values=S, f=lambda x,y:x|y, converter=lambda c: 1 << (ord(c)-ord('a')))
    update = tree.update
    query = tree.query
    for t, a, b in zip(*[iter(q)]*3):
        if t == b'1': update(int(a)-1, b)
        else: print(bin(query(int(a)-1, int(b))).count('1'))

class SegmentTree:
    def __init__(self, n=None, f=max, zero_factory=int, converter=lambda x:x, initial_values=None):
        assert(n or initial_values)
        size = n if n else len(initial_values)
        self.__f, self.__z, self.__c = f, zero_factory, converter
        self.__n = 1 << ((size - 1).bit_length())
        self.__dat = [zero_factory() for _ in range(2 * self.__n)]
        if initial_values:
            zi = self.__get_leaf(0)
            for i, v in enumerate(initial_values): self.__dat[zi + i] = converter(v)
            for i in range(zi-1, -1, -1): self.__dat[i] = f(*self.__get_children(i))

    def update(self, index, value):
        i, v = self.__get_leaf(index), self.__c(value)
        if self.__dat[i] == v: return
        self.__dat[i] = v
        while i:
            i = self.__get_parent(i)
            self.__dat[i] = self.__f(*self.__get_children(i))

    def query(self, from_inclusive, to_exclusive):
        ans = self.__z()
        if to_exclusive <= from_inclusive: return ans
        l, r = self.__get_leaf(from_inclusive), self.__get_leaf(to_exclusive) - 1
        while r - l > 1:
            if self.__is_right(l): ans = self.__f(ans, self.__dat[l])
            if self.__is_left(r): ans, r = self.__f(ans, self.__dat[r]), r-1
            l, r = l//2, self.__get_parent(r)
        ans = self.__f(ans, self.__dat[l])
        if l != r: ans = self.__f(ans, self.__dat[r])
        return ans

    def __get_leaf(self, i): return self.__n + i - 1
    def __get_parent(self, i): return (i-1)//2
    def __get_children(self, i): return (self.__dat[2*i+1], self.__dat[2*i+2])
    def __is_left(self, i): return i&1 == 1
    def __is_right(self, i): return i&1 == 0

if __name__ == '__main__':
    main()