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):
import sys
input = sys.stdin.readline

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

s = [ord(c)-ord('a') for c in s]


    

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]=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] = seg[k*2+1] | seg[k*2+2]

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


ide_ele = set()


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

init(s)


for i in range(q):
    t, x, y = map(str, sys.stdin.readline().split())
    if t == '2':
        l = int(x)-1
        r = int(y)-1
        print(len(query(l, r+1)))
    else:
        i = int(x)-1
        c = {ord(y)-ord('a')}
        update(i, c)

Solution (Python):
from bisect import bisect_left,bisect_right,insort
N = int(input())
S = list(input())
Q = int(input())
D = dict()
D2 = dict()
D3 = dict()

for i in range(97,97+26):
    D[chr(i)] = []
    D2[chr(i)] = []
    D3[chr(i)] = []
for i in range(N):
    D[S[i]].append(i+1)
for i in range(Q):
    t,l,r = input().split()
    if t == str(1):
        k = int(l)
        c = r
        if S[k-1] == c:
            continue
        if bisect_right(D[S[k-1]],k)-bisect_left(D[S[k-1]],k) == 1:
            del D[S[k-1]][bisect_left(D[S[k-1]],k)]
        insort(D[c],k)
        S[k-1] = c
        continue
    l = int(l)
    r = int(r)
    ans = 0
    for i in range(97,97+26):
        X = D[chr(i)]
        X2 = D2[chr(i)]
        X3 = D3[chr(i)]
        if bisect_right(X,r)-bisect_left(X,l) > 0:
            ans += 1
    print(ans)

Solution (Python):
n=int(input())
s=input()
q=int(input())
dic=dict()
for i,j in enumerate("qwertyuioplkjhgfdsazxcvbnm"):
    dic[j]=i
No=2
while n>No:
    No*=2
tree=[set()]*(2*No)
def add(k,x):
    k+=No-1
    tree[k]=set([dic[x]])
    while k>0:
        k=(k-1)//2
        tree[k]=tree[2*k+1]|tree[2*k+2]
def query(l,r):
    L=l+No-1
    R=r+No-1
    s=set()
    while L<=R:
        if R&1:
            s|=tree[R]
            R-=2
        else:
            R-=1
        if L&1:
            L-=1
        else:
            s|=tree[L]
        L>>=1;R>>=1
    return len(s)
for i,j in enumerate(s):
    tree[i+No-1]=set([dic[j]])
for i in range(No-2,-1,-1):
    tree[i]=tree[2*i+1]|tree[2*i+2]
for i in range(q):
    a,b,c=input().split()
    a,b=int(a),int(b)
    if a==1:
        add(b-1,c)
    if a==2:
        c=int(c)
        print(query(b-1,c-1))

Solution (Python):
import sys
def input():
    return sys.stdin.readline()[:-1]
INF = float("inf")


class BIT:
    def __init__(self, N):
        self.N = N
        self.bit = [0] * (N+1)
    def add(self, x, a):
        while x <= self.N:
            self.bit[x] += a
            x += x & -x
    def sum(self, x):
        ret = 0
        while x != 0:
            ret += self.bit[x]
            x -= x & -x
        return ret

N = int(input())
S = list(input())
Q = int(input())
bit = [BIT(N+1) for i in range(26)]
for i in range(N):
    bit[ord(S[i])-97].add(i+1, 1)
for i in range(Q):
    q, x, y = input().split()
    q = int(q)
    if q == 1:
        i = int(x)-1
        bit[ord(S[i])-97].add(i+1, -1)
        S[i] = y
        bit[ord(y)-97].add(i+1, 1)
    else:
        l, r, ans = int(x), int(y), 0
        for i in range(26):
            ans += (bit[i].sum(r)-bit[i].sum(l-1))> 0
        print(ans)

Solution (Python):
NN = 2020202
MOD = 10**9+7
INF = float("inf")


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

    def _sum(self, i):
        s = [0]*26
        while i > 0:
            for idx, v in enumerate(self.bit[i]):
                s[idx] += v
            i -= i & -i
        return s

    def add(self, i, val):
        """i番目にvalを加える"""
        old = self.s[i-1]
        self.s[i - 1] = val
        
        if old == val:
            return

        while i <= self.n:
            
            self.bit[i][ord(val) - ord("a")] += 1
            if 0 <= ord(old) - ord("a") < 26:
                self.bit[i][ord(old) - ord("a")] -= 1

            i += i & -i

    def get_sum(self, l, r):
        """区間[l, r)の和を求める"""
        A = self._sum(r)
        B = self._sum(l-1)
        
        ans = 0
        for idx in range(26):
            if A[idx] > B[idx]:
                ans += 1

        return ans
        


N = int(input())
S = input()
Q = int(input())
query = [list(input().split()) for i in range(Q)]

tree = BIT(N)
for i in range(N):
    tree.add(i+1, S[i])


for i in range(Q):
    if query[i][0] == "1":
        tree.add(int(query[i][1]), query[i][2])
        
    if query[i][0] == "2":
        print(tree.get_sum(int(query[i][1]), int(query[i][2])))

Solution (Python):
from heapq import heappush,heappop,heapify
from collections import deque,defaultdict,Counter
import itertools
from functools import *
from itertools import permutations,combinations,groupby
import sys
import bisect
import string
import math
import time
import random
def Golf():
    *a,=map(int,open(0))
def S_():
    return input()
def IS():
    return input().split()
def LS():
    return [i for i in input().split()]
def I():
    return int(input())
def MI():
    return map(int,input().split())
def LI():
    return [int(i) for i in input().split()]
def LI_():
    return [int(i)-1 for i in input().split()]
def NI(n):
    return [int(input()) for i in range(n)]
def NI_(n):
    return [int(input())-1 for i in range(n)]
def StoI():
    return [ord(i)-97 for i in input()]
def ItoS(nn):
    return chr(nn+97)
def LtoS(ls):
    return ''.join([chr(i+97) for i in ls])
def GI(V,E,Directed=False,index=0):
    org_inp=[]
    g=[[] for i in range(n)]
    for i in range(E):
        inp=LI()
        org_inp.append(inp)
        if index==0:
            inp[0]-=1
            inp[1]-=1
        if len(inp)==2:
            a,b=inp
            g[a].append(b)
            if not Directed:
                g[b].append(a)
        elif len(inp)==3:
            a,b,c=inp
            aa=(inp[0],inp[2])
            bb=(inp[1],inp[2])
            g[a].append(bb)
            if not Directed:
                g[b].append(aa)
    return g,org_inp
def GGI(h,w,search=None,replacement_of_found='.',mp_def={'

    mp=[1]*(w+2)
    found={}
    for i in range(h):
        s=input()
        for char in search:
            if char in s:
                found[char]=((i+1)*(w+2)+s.index(char)+1)
                mp_def[char]=mp_def[replacement_of_found]
        mp+=[1]+[mp_def[j] for j in s]+[1]
    mp+=[1]*(w+2)
    return h+2,w+2,mp,found
def bit_combination(k,n=2):
    rt=[]
    for tb in range(n**k):
        s=[tb//(n**bt)%n for bt in range(k)]
        rt+=[s]
    return rt
def show(*inp,end='\n'):
    if show_flg:
        print(*inp,end=end)
YN=['YES','NO']
Yn=['Yes','No']
 
mo=10**9+7
inf=float('inf')
l_alp=string.ascii_lowercase
u_alp=string.ascii_uppercase


input=lambda: sys.stdin.readline().rstrip()
 
def ran_input():
    import random
    n=random.randint(4,16)
    rmin,rmax=1,10
    a=[random.randint(rmin,rmax) for _ in range(n)]
    return n,a

def ran_input():
    import random
    n=random.randint(4,16)
    rmin,rmax=1,10
    a=[random.randint(rmin,rmax) for _ in range(n)]
    return n,a






class Bit:
    def __init__(self,n):
        self.size=n
        self.m=len(bin(self.size))-2
        self.arr=[0]*(2**self.m+1)
        
    def __str__(self):
        a=[self.sum(i+1)-self.sum(i) for i in range(self.size)]
        return str(a)
        
    def add(self,i,x):
        k=0
        while i<=self.size:
            k+=1
            self.arr[i]+=x
            i+=i&(-i)
        return
    
    def sum(self,i):
        rt=0
        while i>0:
            rt+=self.arr[i]
            i-=i&(-i)
        return rt
    
    def l_bound(self,w):
        if w<=0:
            return 0
        x=0
        k=2**self.m
        while k>0:
            if x+k<self.size and self.arr[x+k]<w:
                w-=self.arr[x+k]
                x+=k
            k//=2
        return x+1
        
    def u_bound(self,w):
        if w<=0:
            return 0
        x=0
        k=2**self.m
        while k>0:
            if x+k<self.size and self.arr[x+k]<=w:
                w-=self.arr[x+k]
                x+=k
            k//=2
        return x+1
        
class Bit0(Bit):
    def add(self,j,x):
        super().add(j+1,x)
    def l_bound(self,w):
        return max(super().l_bound(w)-1,0)
    def u_bound(self,w):
        return max(super().u_bound(w)-1,0)

class Multiset(Bit0):
    def __init__(self,max_v):
        super().__init__(max_v)
    def insert(self,x):
        super().add(x,1)
    def find(self,x):
        return super().l_bound(super().sum(x))
    def __str__(self):
        return str(self.arr)


show_flg=False
show_flg=True


n=I()
s=StoI()
q=I()

bt=[Bit0(n) for i in range(26)]


for i in range(n):
    bt[s[i]].add(i,1)

for _ in range(q):
    t,a,b=input().split()
    if t=='1':
        i,c=int(a)-1,ord(b)-97
        old=s[i]
        s[i]=c
        bt[c].add(i,1)
        bt[old].add(i,-1)
    else:
        l,r=int(a)-1,int(b)-1
        ans=0
        for i in range(26):
            if bt[i].sum(r+1)-bt[i].sum(l)>0:
                ans+=1
        print(ans)

Solution (Python):
class Binary_Indexed_Tree:
    def __init__(self, n):
        self.size = n
        self.tree = [0 for _ in range(n+1)]

    
    def add(self, i, x):
        while i <= self.size:
            self.tree[i] += x
            i += i & (-i)

    
    def sum(self, i):
        s = 0
        while i > 0:
            s += self.tree[i]
            i -= i & (-i)

        return s

alpha_small_dict = {chr(i):i-97 for i in range(97, 97+26)} 
n = int(input())
S = input()
data = [[0 for i in range(n)] for j in range(26)]

bit = [Binary_Indexed_Tree(n) for i in range(26)]
for i,x in enumerate(S):
    bit[alpha_small_dict[x]].add(i+1,1)
    data[alpha_small_dict[x]][i] = 1
q = int(input())
for i in range(q):
    x,y,z = input().split()
    x,y = int(x),int(y)
    
    if x == 1:
        num = alpha_small_dict[z]
        for j in range(26):
            if data[j][y-1] == 1:
                data[j][y-1] = 0
                bit[j].add(y,-1)
                break
        data[num][y-1] = 1
        bit[num].add(y,1)
    else:
        z = int(z)
        ans = 0
        for j in range(26):
            if bit[j].sum(z)-bit[j].sum(y-1) >= 1:
                ans += 1
        print(ans)

Solution (Python):
import sys
sys.setrecursionlimit(10 ** 7)


class SegmentTree:
    """
    引数：
        N: 処理する区間の長さ
        operator: モノイド演算 (max, min, __add__,ラムダ式,関数定義など)
        UNIT: 単位元
        a: 長さNの配列 a で初期化（a を与えない場合、単位元で初期化）
    注意: 内部的には 1-indexed
    """

    def __init__(self, N, operator, unit, a=None):
        self.op = operator
        self.UNIT = unit

        self.N0 = 2**(N-1).bit_length()
        self.tree = [self.UNIT]*(2*self.N0)
        if a != None:
            self.tree[self.N0:self.N0+N] = a[:]
            for k in range(self.N0-1, 0, -1):
                self.tree[k] = self.op(self.tree[2*k], self.tree[2*k+1])

    
    def update(self, k, x):
        k += self.N0
        self.tree[k] = x
        k //= 2
        while k:
            self.tree[k] = self.op(self.tree[2*k], self.tree[2*k+1])
            k //= 2

    
    def query(self, l, r):
        L = l + self.N0
        R = r + self.N0
        s = self.UNIT
        while L < R:
            if R & 1:
                R -= 1
                s = self.op(self.tree[R], s)
            if L & 1:
                s = self.op(s, self.tree[L])
                L += 1
            L >>= 1
            R >>= 1
        return s

    def get(self, k):  
        return self.tree[k + self.N0]

    def all(self):
        return self.tree[1]


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


def ope(x, y):
    r = []
    if type(x) is str and type(y) is str:
        r = [x, y]
    elif type(x) is str:
        r = [x] + y
    elif type(y) is str:
        r = x + [y]
    else:
        r = x + y

    return list(set(r))


seg = SegmentTree(N, ope, '-', S)

Q = int(input())

ans = []
for _ in range(Q):
    q, a, b = input().split()

    if q == '1':
        seg.update(int(a) - 1, b)
    else:
        r = seg.query(int(a) - 1, int(b))
        ans.append(str(len(r)-1))


print("\n".join(ans))

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


def read_ints():
    return list(map(int, read().split()))


def read_a_int():
    return int(read())


def read_matrix(H):
    '''
    H is number of rows
    '''
    return [list(map(int, read().split())) for _ in range(H)]


def read_map(H):
    '''
    H is number of rows
    文字列で与えられた盤面を読み取る用
    '''
    return [read()[:-1] for _ in range(H)]


def read_tuple(H):
    '''
    H is number of rows
    '''
    ret = []
    for _ in range(H):
        ret.append(tuple(map(int, read().split())))
    return ret


def read_col(H, n_cols):
    '''
    H is number of rows
    n_cols is number of cols

    A列、B列が与えられるようなとき
    '''
    ret = [[] for _ in range(n_cols)]
    for _ in range(H):
        tmp = list(map(int, read().split()))
        for col in range(n_cols):
            ret[col].append(tmp[col])

    return ret


def index(a, x):
    'Locate the leftmost value exactly equal to x'
    i = bisect_left(a, x)

    if i != len(a) and a[i] == x:
        return i
    raise ValueError









N = read_a_int()
S = list(read()[:-1])

from collections import defaultdict
from bisect import bisect_left, bisect_right, insort_left
char_idxs = defaultdict(lambda: [])
for i, s in enumerate(S):
    char_idxs[s].append(i)


def get_syurui(char_idxs, l, r):
    ret = 0
    for v in char_idxs.values():
        l_idx = bisect_left(v, l)
        r_idx = bisect_right(v, r)
        
        if r_idx - l_idx > 0:
            ret += 1
    return ret


Q = read_a_int()
for q in range(Q):
    com, a, b = read().split()
    if int(com) == 2:
        a, b = int(a) - 1, int(b) - 1
        print(get_syurui(char_idxs, a, b))
    else:
        i = int(a) - 1
        if S[i] == b:
            continue
        
        tmp = char_idxs[S[i]]  
        del char_idxs[S[i]][index(tmp, i)]
        
        insort_left(char_idxs[b], i)
        
        S[i] = b

Solution (Python):

import sys
input = sys.stdin.readline
INF = 10**9

class SegmentTree:
    def __init__(self, a):
        
        self.op = lambda a, b : max(a, b)
        
        self.e = 0 

        self.n = len(a)
        self.lv = (self.n - 1).bit_length()
        self.size = 2**self.lv
        self.data = [self.e] * (2*self.size - 1)
        
        self._check = lambda x, acc : acc >= x
        self._acc = self.e

        self.initialize(a)

    
    def initialize(self, a):
        for i in range(self.n):
            self.data[self.size + i - 1] = a[i]
        for i in range(self.size-2, -1, -1):
            self.data[i] = self.op(self.data[i*2 + 1], self.data[i*2 + 2])

    
    def update(self, k, x):
        k += self.size - 1
        self.data[k] = x
        while k > 0:
            k = (k - 1) // 2
            self.data[k] = self.op(self.data[2*k+1], self.data[2*k+2])

    
    def fold(self, l, r):
        L = l + self.size; R = r + self.size
        s = self.e
        while L < R:
            if R & 1:
                R -= 1
                s = self.op(s, self.data[R-1])
            if L & 1:
                s = self.op(s, self.data[L-1])
                L += 1
            L >>= 1; R >>= 1
        return s

    def _bisect_forward(self, x, start, k):
        
        if k >= self.size - 1:
            self._acc = self.op(self._acc, self.data[k])
            if self._check(x, self._acc):
                return k - (self.size - 1)
            else:
                return -1
        width = 2**(self.lv - (k+1).bit_length() + 1)
        mid = (k+1) * width + width // 2 - self.size 
        
        if mid <= start:
            return self._bisect_forward(x, start, 2*k + 2)
        
        tmp_acc = self.op(self._acc, self.data[k])
        if start <= mid - width // 2 and not self._check(x, tmp_acc):
            self._acc = tmp_acc
            return -1
        
        vl = self._bisect_forward(x, start, 2*k + 1)
        if vl != -1:
            return vl
        return self._bisect_forward(x, start, 2*k + 2)
    
    
    def bisect_forward(self, x, start=None):
        if start:
            ret = self._bisect_forward(x, start, 0)
        else:
            ret = self._bisect_forward(x, 0, 0)
        self._acc = self.e
        return ret

    def _bisect_backward(self, x, start, k):
        
        if k >= self.size - 1:
            self._acc = self.op(self._acc, self.data[k])
            if self._check(x, self._acc):
                return k - (self.size - 1)
            else:
                return -1
        width = 2**(self.lv - (k+1).bit_length() + 1)
        mid = (k+1) * width + width // 2 - self.size 
        
        if mid >= start:
            return self._bisect_backward(x, start, 2*k + 1)
        
        tmp_acc = self.op(self._acc, self.data[k])
        if start > mid + width // 2 and not self._check(x, tmp_acc):
            self._acc = tmp_acc
            return -1
        
        vl = self._bisect_backward(x, start, 2*k + 2)
        if vl != -1:
            return vl
        return self._bisect_backward(x, start, 2*k + 1)
    
    
    def bisect_backward(self, x, start=None):
        if start:
            ret = self._bisect_backward(x, start, 0)
        else:
            ret = self._bisect_backward(x, self.n, 0)
        self._acc = self.e
        return ret

n = int(input())
s = input().rstrip()
bit_array = [[0] * n for _ in range(26)]
orda = ord("a")
for i, ch in enumerate(s):
    bit_array[ord(ch) - orda][i] = 1

sts = []
for i in range(26):
    sts.append(SegmentTree(bit_array[i]))

q = int(input())
for _ in range(q):
    q1, q2, q3 = [item for item in input().split()]
    if q1 == "1":
        iq = int(q2) - 1
        cq = q3
        for index in range(26):
            sts[index].update(iq, 0)
        sts[ord(cq) - orda].update(iq, 1)
    else:
        lq = int(q2) - 1
        rq = int(q3) 
        ret = 0
        for index in range(26):
            if sts[index].fold(lq, rq) != 0:
                ret += 1
        print(ret)

Solution (Python):
from collections import defaultdict
n = int(input())
sl = list(input())
q = int(input())



class BIT:
    def __init__(self, n):
        self.n = n
        self.data = [0] * (n + 1)
        self.el = [0] * (n + 1)

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

    def add(self, i, x):
        assert i > 0
        self.el[i] += x
        while i <= self.n:
            self.data[i] += x
            i += i & -i

    def get(self, i, j=None):
        if j is None:
            return self.el[i]
        return self.sum(j) - self.sum(i)


dic = defaultdict(lambda: BIT(n))
ascii_lowercase = 'abcdefghijklmnopqrstuvwxyz'
for idx, s in enumerate(sl):
    dic[s].add(idx+1, 1)
for _ in range(q):
    a, b, c = map(str, input().split())
    if a == "1":
        b = int(b)
        dic[sl[b-1]].add(b, -1)
        dic[c].add(b, 1)
        sl[b-1] = c
    else:
        b = int(b)
        c = int(c)
        ans = 0
        for s in ascii_lowercase:
            if dic[s].get(b-1, c) > 0:
                ans += 1
        print(ans)

Solution (Python):
from sys import stdin

d = {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f': 5, 'g': 6, 'h': 7, 'i': 8, 'j': 9, 'k': 10, 'l': 11, 'm': 12, 'n': 13, 'o': 14, 'p': 15, 'q': 16, 'r': 17, 's': 18, 't': 19, 'u': 20, 'v': 21, 'w': 22, 'x': 23, 'y': 24, 'z': 25}

input = stdin.readline

n = int(input())

tree = [[0] * n * 2 for _ in range(26)]

def build(arr):
    for i in range(n):
        tree[ddd][n + i] = arr[i]

    for i in range(n - 1, 0, -1):
        tree[ddd][i] = tree[ddd][i << 1] + tree[ddd][i << 1 | 1]

def update(p, value):
    p += n
    tree[ddd][p] = value

    i = p

    while i > 1:
        tree[ddd][i >> 1] = tree[ddd][i] + tree[ddd][i ^ 1]
        i >>= 1

def query(l, r):
    res = 0

    l += n
    r += n

    while l < r:

        if l & 1:
            res += tree[ddd][l]
            l += 1

        if r & 1:
            r -= 1
            res += tree[ddd][r]

        l >>= 1
        r >>= 1

    return res

s = list(input())

arrs = [[0] * n for _ in range(26)]

for i in range(n):
    arrs[d[s[i]]][i] = 1

for ddd in range(26):
    build(arrs[ddd])

for _ in range(int(input())):
    t = input().split()

    if t[0] == '1':
        i, c = t[1:]
        i = int(i) - 1

        new = d[c]
        cur = d[s[i]]

        s[i] = c

        ddd = cur
        update(i, 0)

        ddd = new
        update(i, 1)

    if t[0] == '2':
        l, r = map(int, t[1:])
        l -= 1
        r -= 1

        ans = 0

        for ddd in range(26):
            if query(l, r + 1) != 0:
                ans += 1

        print(ans)

Solution (Python):
class SegmentTree:
	def __init__(self, orig, func, unit):
		_len = len(orig)
		self.func = func
		self.size = 1 << (_len - 1).bit_length()
		self.tree = [unit] * self.size + orig + [unit] * (self.size - _len)
		self.unit = unit

		for i in range(self.size - 1, 0, -1):
			self.tree[i] = func(self.tree[i * 2], self.tree[i * 2 + 1])

	def update(self, i, v):
		i += self.size
		self.tree[i] = v
		while i:
			i //= 2
			self.tree[i] = self.func(self.tree[i * 2], self.tree[i * 2 + 1])

	def find(self, l, r):
		l += self.size
		r += self.size
		ret = self.unit
		while l < r:
			if l & 1:
				ret = self.func(ret, self.tree[l])
				l += 1
			if r & 1:
				r -= 1
				ret = self.func(ret, self.tree[r])
			l //= 2
			r //= 2
		return ret

import sys
input = sys.stdin.readline
from operator import or_

def main():
	input()
	seg = SegmentTree([1 << ord(x) - 97 for x in input()[:-1]], or_, 0)
	ans = []
	for _ in range(int(input())):
		f, x, y = input().split()
		if f == "1":
			seg.update(int(x) - 1, 1 << ord(y) - 97)
		else:
			ans.append(bin(seg.find(int(x) - 1, int(y))).count("1"))
	print(*ans)

if __name__=="__main__":
	main()

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

L = 20
M = [1<<i for i in range(L)]
T = [[0]*m for m in M]

o = ord('a')

for i, c in enumerate(S):
    T[-1][i] = 1<<(ord(c)-o)

for l in range(L-2, -1, -1):
    for i in range(M[l]):
        T[l][i] = T[l+1][i*2] | T[l+1][i*2+1]
    
def q(layer, n, l, r):
    length_block = (1<<(L-1))//M[layer]
    ml = length_block*n
    mr = ml + length_block

    if l==ml and r==mr:
        return T[layer][n]
    
    center = ml + length_block//2

    ret = 0
    if l<center: ret |= q(layer+1, n*2  , l, min(r,center))
    if r>center: ret |= q(layer+1, n*2+1, max(l,center), r)

    return ret

Q = int(input())
for _ in range(Q):
    t, a1, a2 = input().split()
    if t=='1':
        i = int(a1)-1
        c = a2
        T[-1][i] = 1<<(ord(c)-o)
        for l in range(L-2, -1, -1):
            i = i//2
            T[l][i] = T[l+1][i*2] | T[l+1][i*2+1]
        
    else:
        l = int(a1)-1
        r = int(a2)
        x = q(0, 0, l, r)
        ans = 0
        for i in range(26):
            if (x>>i)&1: ans+=1
        print(ans)

Solution (Python):
n=int(input())
s=list(input())
q=int(input())
def segfunc(x,y):
    return x|y
def init(init_val,var):
    
    for i in range(n):
        seg[var][i+num-1]=init_val[i]    
    
    for i in range(num-2,-1,-1) :
        seg[var][i]=segfunc(seg[var][2*i+1],seg[var][2*i+2]) 
    
def update(k,x,var):
    k += num-1
    seg[var][k] = x
    while k:
        k = (k-1)//2
        seg[var][k] = segfunc(seg[var][k*2+1],seg[var][k*2+2])
    
def query(p,q,var):
    if q<=p:
        return ide_ele
    p += num-1
    q += num-2
    res=ide_ele
    while q-p>1:
        if p&1 == 0:
            res = segfunc(res,seg[var][p])
        if q&1 == 1:
            res = segfunc(res,seg[var][q])
            q -= 1
        p = p//2
        q = (q-1)//2
    if p == q:
        res = segfunc(res,seg[var][p])
    else:
        res = segfunc(segfunc(res,seg[var][p]),seg[var][q])
    return res


ide_ele = 0


num =2**(n-1).bit_length()
seg=[[ide_ele]*2*num for i in range(26)]
for i in range(n):
    update(i,1,ord(s[i])-97)
for i in range(q):
    a,b,c=input().split()
    if a=="1":
        update(int(b)-1,0,ord(s[int(b)-1])-97)
        s[int(b)-1]=c
        update(int(b)-1,1,ord(c)-97)
    else:
        ans=0
        for j in range(26):
            ans+=query(int(b)-1,int(c),j)
        print(ans)

Solution (Python):
import sys
readline = sys.stdin.buffer.readline
kijun = ord("a")
n = int(readline())
s = readline().rstrip().decode('utf-8')
q = int(readline())
lst1 = [0]*n

def pow(n,p): 
    res = 1
    while p > 0:
        if p % 2 == 0:
            n = n ** 2
            p //= 2
        else:
            res = res * n
            p -= 1
    return res

for i in range(n):
    lst1[i] = pow(2,(ord(s[i])-kijun))

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): 
    if q<=p:
        return ide_ele
    p += num-1
    q += num-2
    res=ide_ele
    while q-p>1:
        if p&1 == 0:
            res = segfunc(res,seg[p])
        if q&1 == 1:
            res = segfunc(res,seg[q])
            q -= 1
        p = p//2
        q = (q-1)//2
    if p == q:
        res = segfunc(res,seg[p])
    else:
        res = segfunc(segfunc(res,seg[p]),seg[q])
    return res


"""
最小値のセグ木 → 10**9　(最小値の更新に影響しないため)
　　和のセグ木 → 0　(上の単位元の説明を参照)
　　積のセグ木 → 1　(上の単位元の説明を参照)
　　gcdのセグ木 → 0　(gcdを更新しない値は0)
"""
ide_ele = 0


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

init(lst1)

def judge(u):
    res = 0
    for i in range(27):
        if u>>i & 1:
            res += 1
    return res

for i in range(q):
    t,x,y = readline().rstrip().decode('utf-8').split()
    if t == "1":
        update(int(x)-1,pow(2,ord(y)-kijun))
    else:
        print(judge(query(int(x)-1,int(y))))

Solution (Python):
import sys

sys.setrecursionlimit(500000)
def input():
    return sys.stdin.readline()[:-1]

class BIT:
            
    def __init__(self, L):
        self.N = len(L)
        self.bit = [0]*self.N
        
        
        self.N0 = 1
        while self.N0*2 <= self.N:
            self.N0 *= 2

    def add(self, a, w):
        x = a + 1
        for i in range(1000):
            self.bit[x-1] += w
            x += x & -x
            if x > self.N:
                break

    def sum(self, a):
        x = a+1
        ret = 0
        for i in range(1000):
            ret += self.bit[x-1]
            x -= x & -x
            if x <= 0:
                break        
        return ret

    
    def lower_bound(self, w):
        if w<=0:
            return 0
        x = 0
        k = self.N0
        while k>0:
            if x+k<=self.N:
                if self.bit[x+k-1]<w:
                    w-=self.bit[x+k-1]
                    x+=k
            k//=2
        return x+1


def main():
    
    
    
    N = int(input())

    B = [BIT([0]*N) for i in range(26)]

    S = list(input())

    for i in range(N):
        B[ord(S[i]) - ord("a")].add(i, 1)

    Q = int(input())

    for i in range(Q):
        a,b,c = input().split()
        if a=="1":
            
            index = int(b)-1
            c = c
            if not S[index]==c:
                old = ord(S[index]) - ord("a")
                num = ord(c) - ord("a")
                B[num].add(index, 1)
                B[old].add(index, -1)
                S[index] = c
        else:
            
            
            l = int(b)-1
            r = int(c)-1
            ans = 0
            for j in range(26):
                if l==0:
                    if B[j].sum(r)>0:
                        ans+=1
                else:
                    if B[j].sum(r)-B[j].sum(l-1)>0:
                        ans+=1

            print(ans)

if __name__ == '__main__':
    main()

Solution (Python):
import sys
input = sys.stdin.readline
class SegmentTree():
    def __init__(self,size,unit,f):
        self.size=size
        self.data=[unit for _ in range(2*size)]
        self.unit=unit
        self.f=f
    def update(self,i,x):
        c=self.data
        f=self.f
        i+=self.size
        c[i]=x
        while i>1:
            i//=2
            c[i]=f(c[i*2],c[i*2+1])
    def add(self,i,x):
        c=self.data
        f=self.f
        i+=self.size
        c[i]=f(c[i],x)
        while i>1:
            i//=2
            c[i]=f(c[i*2],c[i*2+1])
    def query(self,l,r):
        c=self.data
        f=self.f
        x=self.unit
        y=self.unit
        l+=self.size
        r+=self.size
        while l<r:
            if l%2:
                x=f(x,c[l])
                l+=1
            if r%2:
                r-=1
                y=f(c[r],y)
            l//=2
            r//=2
        return f(x,y)
def main():
    N = int( input())
    S = list( input())
    Q = int( input())
    Query = [ tuple( input().split()) for _ in range(Q)]
    for i in range(40):
        if N < pow(2,i):
            n = pow(2,i)
            break
    A = [SegmentTree(n, 0, lambda a,b : a+b) for _ in range(26)]
    a = ord('a')
    for i in range(N):
        A[ord(S[i]) - a].update(i, 1)
    ANS = []
    for t, i, c in Query:
        if t == '1':
            i = int(i)
            A[ord(S[i-1])-a].update(i-1, 0)
            A[ord(c)-a].update(i-1,1)
            S[i-1] = c
        else:
            i, c = int(i), int(c)
            ans = 0
            for j in range(26):
                if A[j].query(i-1, c) > 0:
                    ans += 1
            ANS.append(ans)
    print('\n'.join( map(str, ANS)))

if __name__ == '__main__':
    main()