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
from operator import or_


def read():
    N = int(input().strip())
    S = input().strip()
    Q = int(input().strip())
    return N, S, Q


class SegmentTree():
    
    def __init__(self, size, op=min, init_value=10**8):
        """初期化"""
        self.size = size
        self.op = op
        self.init_value = init_value
        n = 2 ** ((size-1).bit_length())
        treesize = n * 2
        st = [init_value for i in range(treesize)]
        self.st = st

    @classmethod
    def from_array(cls, a, op=min, init_value=10**8):
        st = cls(len(a), op=op, init_value=init_value)
        for i, x in enumerate(a):
            st.update(i, x)
        return st

    def update(self, key, value):
        """値の更新"""
        offset = len(self.st) // 2
        k = offset + key
        self.st[k] = value
        k >>= 1
        while k > 0:
            self.st[k] = self.op(self.st[k * 2], self.st[k * 2 + 1])
            k >>= 1

    def _query_bottomup(self, a, b):
        """区間[a, b) に対する累積操作
        """
        offset = len(self.st) // 2
        a += offset
        b += offset - 1
        s = self.init_value
        while a < b:
            if a & 1 == 1:
                s = self.op(s, self.st[a])
                a += 1
            a >>= 1
            if b & 1 == 0:
                s = self.op(s, self.st[b])
                b -= 1
            b >>= 1
        if a == b:
            s = self.op(s, self.st[a])
        return s

    def _query_topdown(self, a, b, k, l, r):
        """区間[a, b) に対する累積操作
        k: 着目しているノード (1-indexed)
        l: 探索区間 st[l, r) の左端 (0-indexed)
        r: 探索区間 st[l, r) の右端 (0-indexed)
        """
        if r <= a or b <= l:
            return self.init_value
        if a <= l and r <= b:
            return self.st[k]
        mid = (l + r) // 2
        lv = self._query_topdown(a, b, k * 2, l, mid)
        rv = self._query_topdown(a, b, k * 2 + 1, mid, r)
        return self.op(lv, rv)

    def query(self, a, b):
        """区間[a, b) に対する累積操作"""
        if a > b:
            raise ValueError("a must be less than equal b.")
        return self._query_topdown(a, b, k=1, l=0, r=len(self.st)//2)
        


def solve_online(N, S, Q):
    tree = SegmentTree(N, op=or_, init_value=0)
    C = [ord(s) - ord("a") for s in S]
    for i in range(N):
        c = ord(S[i]) - ord("a")
        tree.update(i, 1 << c)

    for _ in range(Q):
        op, a, b = input().strip().split()
        if op == "1":
            i, c = int(a)-1, ord(b) - ord("a")
            tree.update(i, 1 << c)
        elif op == "2":
            l, r = int(a)-1, int(b)-1
            b = tree.query(l, r+1)
            s = 0
            while b > 0:
                if b & 1 == 1:
                    s += 1
                b >>= 1
            print(s)


if __name__ == '__main__':
    inputs = read()
    outputs = solve_online(*inputs)
    if outputs is not None:
        print("%s" % str(outputs))

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


def read():
    N = int(input().strip())
    S = input().strip()
    Q = int(input().strip())
    return N, S, Q


class SegmentTree():
    
    def __init__(self, size, op=min, init_value=10**8):
        """初期化"""
        self.size = size
        self.op = op
        self.init_value = init_value
        n = 2 ** ((size-1).bit_length())
        treesize = n * 2
        st = [init_value for i in range(treesize)]
        self.st = st

    @classmethod
    def from_array(cls, a, op=min, init_value=10**8):
        st = cls(len(a), op=op, init_value=init_value)
        for i, x in enumerate(a):
            st.update(i, x)
        return st

    def update(self, key, value):
        """値の更新"""
        offset = len(self.st) // 2
        k = offset + key
        self.st[k] = value
        k >>= 1
        while k > 0:
            self.st[k] = self.op(self.st[k * 2], self.st[k * 2 + 1])
            k >>= 1

    def _query_bottomup(self, a, b):
        """区間[a, b) に対する累積操作
        """
        offset = len(self.st) // 2
        a += offset
        b += offset - 1
        s = self.init_value
        while a < b:
            if a & 1 == 1:
                s = self.op(s, self.st[a])
                a += 1
            a >>= 1
            if b & 1 == 0:
                s = self.op(s, self.st[b])
                b -= 1
            b >>= 1
        if a == b:
            s = self.op(s, self.st[a])
        return s

    def _query_topdown(self, a, b, k, l, r):
        """区間[a, b) に対する累積操作
        k: 着目しているノード (1-indexed)
        l: 探索区間 st[l, r) の左端 (0-indexed)
        r: 探索区間 st[l, r) の右端 (0-indexed)
        """
        if r <= a or b <= l:
            return self.init_value
        if a <= l and r <= b:
            return self.st[k]
        mid = (l + r) // 2
        lv = self._query_topdown(a, b, k * 2, l, mid)
        rv = self._query_topdown(a, b, k * 2 + 1, mid, r)
        return self.op(lv, rv)

    def query(self, a, b):
        """区間[a, b) に対する累積操作"""
        if a > b:
            raise ValueError("a must be less than equal b.")
        
        return self._query_bottomup(a, b)


def solve_online(N, S, Q):
    tree = SegmentTree(N, op=or_, init_value=0)
    C = [ord(s) - ord("a") for s in S]
    for i in range(N):
        c = ord(S[i]) - ord("a")
        tree.update(i, 1 << c)

    for _ in range(Q):
        op, a, b = input().strip().split()
        if op == "1":
            i, c = int(a)-1, ord(b) - ord("a")
            tree.update(i, 1 << c)
        elif op == "2":
            l, r = int(a)-1, int(b)-1
            b = tree.query(l, r+1)
            s = 0
            while b > 0:
                if b & 1 == 1:
                    s += 1
                b >>= 1
            print(s)


if __name__ == '__main__':
    inputs = read()
    outputs = solve_online(*inputs)
    if outputs is not None:
        print("%s" % str(outputs))

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


ide_ele = 0


class SegTree:
    """
    init(init_val, ide_ele): 配列init_valで初期化 O(N)
    update(k, x): k番目の値をxに更新 O(logN)
    query(l, r): 区間[l, r)をsegfuncしたものを返す O(logN)
    """

    def __init__(self, init_val, segfunc, ide_ele):
        """
        init_val: 配列の初期値
        segfunc: 区間にしたい操作
        ide_ele: 単位元
        n: 要素数
        num: n以上の最小の2のべき乗
        tree: セグメント木(1-index)
        """
        n = len(init_val)
        self.segfunc = segfunc
        self.ide_ele = ide_ele
        self.num = 1 << (n - 1).bit_length()
        self.tree = [ide_ele] * 2 * self.num
        
        for i in range(n):
            self.tree[self.num + i] = init_val[i]
        
        for i in range(self.num - 1, 0, -1):
            self.tree[i] = self.segfunc(self.tree[2 * i], self.tree[2 * i + 1])

    def update(self, k, x):
        """
        k番目の値をxに更新
        k: index(0-index)
        x: update value
        """
        k += self.num
        self.tree[k] = x
        while k > 1:
            self.tree[k >> 1] = self.segfunc(self.tree[k], self.tree[k ^ 1])
            k >>= 1

    def query(self, l, r):
        """
        [l, r)のsegfuncしたものを得る
        l: index(0-index)
        r: index(0-index)
        """
        res = self.ide_ele

        l += self.num
        r += self.num
        while l < r:
            if l & 1:
                res = self.segfunc(res, self.tree[l])
                l += 1
            if r & 1:
                res = self.segfunc(res, self.tree[r - 1])
            l >>= 1
            r >>= 1
        return res


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

ls = []

for ch in s:
    ls.append(1 << (ord(ch) - 97))

seg = SegTree(ls, segfunc, ide_ele)

for i in range(q):
    que = input().split()
    if que[0] == '1':
        iq = int(que[1])
        cq = que[2]
        seg.update(iq-1, 1 << (ord(cq) - 97))
    else:
        lq = int(que[1])
        rq = int(que[2])
        ret = seg.query(lq-1, rq)
        print(str(bin(ret)).count('1'))

Solution (Python):
import sys
import math
import bisect
def input():
    return sys.stdin.readline()[:-1]

n=int(input())
s=list(input())
q=int(input())
ans=[]
dic = {}

for i in range(97,97+26):
    dic[chr(i)]=[]

for num,i in enumerate(s):
    dic[i].append(num)

for i in range(q):
    num,l,r = map(str,input().split())
    if int(num)==1:
        l=int(l)-1
        if s[l] == r:
            continue
        else:
            dic[s[l]].pop(bisect.bisect_left(dic[s[l]],l))
            bisect.insort_left(dic[r],l)
            s[l] = r
    else:
        cnt=0
        l=int(l)
        r=int(r)
        for li in dic.values():
            ind = bisect.bisect_left(li,l-1)
            if ind>=len(li):continue
            if li[ind]<=r-1:
                cnt+=1
        ans.append(cnt)

print(*ans,sep="\n")

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

'''
'init(a)': 配列aで初期化。O(N)
'update(k,x)': a[k]をxに変更 O(logN)
'query(p,q)': [p,q)について "segfunc" したものを返す O(logN)
'ide_ele' : 単位元。
'''




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



ide_ele = 0


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


init_val = []
for s in S:
    init_val.append(1 << (ord(s)-ord('a')))
init(init_val)

for _ in range(Q):
    t, s, u = input().split()
    if t == '1':
        update(int(s)-1, 1 << (ord(u)-ord('a')))
    else:
        print(bin(query(int(s)-1, int(u))).count('1'))

Solution (Python):
import sys
import bisect

N = int(sys.stdin.readline().rstrip())
S = list(sys.stdin.readline().rstrip())
Q = int(sys.stdin.readline().rstrip())

idx = {chr(ord("a") + i): [] for i in range(26)}

for i, s in enumerate(S):
    idx[s].append(i + 1)

for _ in range(Q):
    t, i, c = sys.stdin.readline().rstrip().split()
    i = int(i)
    if t == "1":
        if S[i - 1] != c:
            idx[S[i - 1]].remove(i)
            bisect.insort(idx[c], i)
            S[i - 1] = c
    else:
        c = int(c)
        ans = 0
        for a, id in idx.items():
            x = bisect.bisect_left(id, i)
            y = bisect.bisect_right(id, c)
            if y - x:
                ans += 1
        print(ans)

Solution (Python):
import sys
import bisect
import copy

N = int(sys.stdin.readline().rstrip())
S = list(sys.stdin.readline().rstrip())
Q = int(sys.stdin.readline().rstrip())

cnt = [0] * 26
cumcnt = [cnt]

for i, s in enumerate(S):
    tmp = copy.copy(cumcnt[i])
    tmp[ord(s) - ord("a")] += 1
    cumcnt.append(tmp)

q_remove = {}
q_add = {}

for _ in range(Q):
    t, i, c = sys.stdin.readline().rstrip().split()
    t = int(t)
    i = int(i)
    d = S[i - 1]
    if t == 1:
        if d != c:
            if d not in q_remove.keys():
                q_remove[d] = [i]
            else:
                bisect.insort(q_remove[d], i)
            if c not in q_add.keys():
                q_add[c] = [i]
            else:
                bisect.insort(q_add[c], i)
            S[i - 1] = c 
    else:
        c = int(c)
        cnt_l = copy.copy(cumcnt[i - 1])
        cnt_r = copy.copy(cumcnt[c])
        for q, idx in q_add.items():
            x = bisect.bisect_right(idx, i - 1)
            y = bisect.bisect_right(idx, c)
            cnt_l[ord(q) - ord("a")] += x
            cnt_r[ord(q) - ord("a")] += y
        for q, idx in q_remove.items():
            x = bisect.bisect_right(idx, i - 1)
            y = bisect.bisect_right(idx, c)
            cnt_l[ord(q) - ord("a")] -= x
            cnt_r[ord(q) - ord("a")] -= y
        ans = 0
        for l, r in zip(cnt_l, cnt_r):
            if r - l > 0:
                ans += 1
        print(ans)

Solution (Python):
n=int(input())
s=list(input())
q=int(input())

def ctoi(c):
  return ord(c)-97
class Bit:
  def __init__(self, n):
    self.size = n
    self.tree = [[0]*(n+1) for _ in range(26)]
  def query(self,a,i):
    r = 0
    while i > 0:
      r += self.tree[a][i]
      i -= i & -i
    return r
  def update(self,i,a,x):
    while i<=n:
      self.tree[a][i]+=x
      i+=i&(-i)
bi=Bit(n)
for i in range(n):
  bi.update(i+1,ctoi(s[i]),1)
  
for _ in range(q):
  a,b,c=input().split()
  a,b=int(a),int(b)
  if a==1 and s[b-1]!=c:
    bi.update(b,ctoi(s[b-1]),-1)
    bi.update(b,ctoi(c),1)
    s[b-1]=c
  elif a==2:
    c=int(c)
    right=[bi.query(i,c) for i in range(26)]
    left=[bi.query(i,b-1) for i in range(26)]
    ans=0
    for r,l in zip(right,left):
      if r-l>0:
        ans+=1
    print(ans)

Solution (Python):
class SEGTree:
    def __init__(self,n):
        self.Unit=0
        i=1
        while(i<n):
            i*=2
        self.SEG=[self.Unit]*(2*i-1)
        self.d=i
    def update(self,i,x):
        i+=self.d-1
        self.SEG[i]=1<<x
        while i>0:
            i=(i-1)//2
            self.SEG[i]=self.SEG[i*2+1]|self.SEG[i*2+2]
    def find(self,a,b,k,l,r):
        if r<=a or b<=l:
            return self.Unit
        if a<=l and r<=b:
            return self.SEG[k]
        else:
            c1=self.find(a,b,2*k+1,l,(l+r)//2)
            c2=self.find(a,b,2*k+2,(l+r)//2,r)
            return c1|c2
    def get(self,a,b):
        return self.find(a,b,0,0,self.d)
def bitcnt(x):
    res=0
    while x>0:
        if x&1:
            res+=1
        x//=2
    return res

n=int(input())
s=input()
q=int(input())
seg=SEGTree(n)
for i in range(n):
    seg.update(i,ord(s[i])-97)
for i in range(q):
    q,x,y=input().split()
    if q=='1':
        seg.update(int(x)-1,ord(y)-97)
    else:
        x,y=int(x)-1,int(y)
        bit=seg.get(x,y)
        print(bitcnt(bit))

Solution (Python):
def main():
    global s,ide_ele,num,seg
    n = int(input())
    s = list(input())
    for i in range(n):
        s[i] = ord(s[i])-97
    ide_ele = 0
    num = 2**(n-1).bit_length()
    seg = [[ide_ele for _ in range(2*num)] for _ in range(26)]
    for i in range(n):
        seg[s[i]][i+num-1] = 1
    for a in range(26):
        for i in range(num-2,-1,-1) :
            seg[a][i] = max(seg[a][2*i+1],seg[a][2*i+2])
    q = int(input())
    for _ in range(q):
        QUERY = list(input().split())
        QUERY[0], QUERY[1] = int(QUERY[0]), int(QUERY[1])
        if QUERY[0] == 1:
            x = ord(QUERY[2])-97
            k = QUERY[1]-1
            pre = s[k]
            s[k] = x
            k += num-1
            seg[pre][k] = 0
            seg[x][k] = 1
            while k:
                k = (k-1)//2
                seg[pre][k] = max(seg[pre][k*2+1],seg[pre][k*2+2])
                seg[x][k] = max(seg[x][k*2+1],seg[x][k*2+2])
        if QUERY[0] == 2:
            P, Q = QUERY[1]-1, int(QUERY[2])
            if Q <= P:
                print(ide_ele)
                break
            P += num-1
            Q += num-2
            ans = ide_ele
            for i in range(26):
                res = ide_ele
                p,q = P,Q
                while q-p > 1:
                    if p&1 == 0:
                        res = max(res,seg[i][p])
                    if q&1 == 1:
                        res = max(res,seg[i][q])
                        q -= 1
                    p = p//2
                    q = (q-1)//2
                if p == q:
                    res = max(res,seg[i][p])
                else:
                    res = max(max(res,seg[i][p]),seg[i][q])
                ans += res
            print(ans)

if __name__ == "__main__":
    main()

Solution (Python):

import sys

sys.setrecursionlimit(10 ** 8)
ni = lambda: int(sys.stdin.readline())
nm = lambda: map(int, sys.stdin.readline().split())
nl = lambda: list(nm())
ns = lambda: sys.stdin.readline().rstrip()

N = ni()
S = ns()
assert len(S) == N
Q = ni()
qs = []
for i in range(Q):
    q = ns().split()
    qs.append(q)


def main():
    orda = ord("a")
    ords = [ord(ch) - orda for ch in S]
    bits = [BIT(N) for _ in range(26)]
    for i, ch in enumerate(ords):
        bits[ch].add(i + 1, +1)  
    for q in qs:
        if q[0] == "1":
            j = int(q[1])  
            nch = ord(q[2]) - orda
            och = ords[j - 1]
            if nch != och:
                ords[j - 1] = nch
                bits[och].add(j, -1)
                bits[nch].add(j, +1)
        else:
            assert q[0] == "2"
            l, r = int(q[1]), int(q[2])  
            n = 0
            for i in range(26):
                b = bits[i]
                if b.sum(r) - b.sum(l - 1) > 0:
                    n += 1
            print(n)



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

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

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


main()

Solution (Python):
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):
        
        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)

n = int(input())
s = list(input())
q = int(input())
ord_a = ord("a")
queries = [tuple(input().split()) for i in range(q)]
bits = [BIT(n) for i in range(26)]
for k,v in enumerate(s,1):
  bits[ord(v)-ord_a].add(k,1)
for query,i,c in queries:
  if query == "1":
    i = int(i)
    prev = s[i-1]
    if prev != c:
      bits[ord(prev)-ord_a].add(i,-1)
      bits[ord(c)-ord_a].add(i,1)
      s[i-1] = c
  elif query == "2":
    l,r = int(i),int(c)
    res = 0
    for bit in bits:
      if bit.get(r,l-1):
        res += 1
    print(res)

Solution (Python):
from bisect import bisect_left,bisect_right
import string 

dic = {c:[] for c in string.ascii_lowercase}

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

for i,c in enumerate(s,start=1):
  dic[c].append(i)
  
for i in range(q):
  p,l,r = map(str,input().split())
  if p =='1':
    j = int(l)
    if r == s[j-1]:
      continue
    c = s[j-1]    
    dic[c].pop(bisect_left(dic[c],j))
    dic[r].insert(bisect_left(dic[r],j),j)
    s[j-1] = r
  else:
    ans = 0
    l = int(l)
    r = int(r)
    for c in string.ascii_lowercase:
      pl = bisect_left(dic[c],l)
      if pl < len(dic[c]):
        if dic[c][pl] <= r:
          ans += 1
    print(ans)

Solution (Python):

import sys

sys.setrecursionlimit(300000)

class BinaryIndexedTree(object):

    def __init__(self, n):
        
        self.n = n
        self.vals = [0] * (n + 1)

    def add(self, i, v):
        while i <= self.n:
            self.vals[i] += v
            i += i & -i

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

    def sum_range(self, l, r):
        
        return self.sum(r) - self.sum(l - 1)


def solve(N, S, Q, queries):
    trees = []
    for i in range(26):
        trees.append(BinaryIndexedTree(N))

    s = []
    for i, c in enumerate(S):
        c_idx = ord(c) - ord('a')
        if 'a' <= c <= 'z':
            trees[c_idx].add(i + 1, 1)
        s.append(c)

    for q in queries:
        if q[0] == '1':
            i, c = int(q[1]), q[2]
            p = s[i - 1]
            s[i - 1] = c
            trees[ord(p) - ord('a')].add(i, -1)
            trees[ord(c) - ord('a')].add(i, 1)
        if q[0] == '2':
            l, r = int(q[1]), int(q[2])
            ret = 0
            for tree in trees:
                cnt = tree.sum_range(l, r)
                if cnt:
                    ret += 1
            print(ret)
        
        
        

    return

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 = str(next(tokens))
    Q = int(next(tokens))
    q = []
    for i in range(Q):
        q.append(list(map(str, input().split())))
    solve(N, S, Q, q)

if __name__ == '__main__':
    main()

Solution (Python):
import sys,queue,math,copy,itertools,bisect,collections,heapq

def main():
    sys.setrecursionlimit(10**7)
    INF = 10**18
    MOD = 10**9 + 7
    LI = lambda : [int(x) for x in sys.stdin.readline().split()]
    NI = lambda : int(sys.stdin.readline())

    N = NI()

    N0 = 2**(N.bit_length())
    st = [0] * (N0*2)

    def gindex(l, r):
        L = l + N0; R = r + N0
        lm = (L // (L & -L)) // 2
        rm = (R // (R & -R)) // 2
        while L < R:
            if R <= rm:
                yield R - 1
            if L <= lm:
                yield L - 1
            L //= 2; R //= 2
        while L > 0:
            yield L - 1
            L //= 2

    def update(i,s):
        x = 2 ** (ord(s) - ord('a'))
        i += N0-1
        st[i] = x
        while i > 0:
            i = (i-1) // 2
            st[i] = st[i*2+1] | st[i*2+2]

    def query(l,r):
        l += N0
        r += N0
        ret = 0

        while l < r:
            if l % 2:
                ret |= st[l-1]
                l += 1
            if r % 2:
                r -= 1
                ret |= st[r-1]
            l //= 2 ; r //= 2

        return ret


    for i,s in enumerate(sys.stdin.readline().rstrip()):
        update(i+1,s)
    Q = NI()
    for _ in range(Q):
        c,a,b = sys.stdin.readline().split()
        if c == '1':
            update(int(a),b)
        else:
            ret = query(int(a),int(b)+1)
            cnt = 0
            b = 1
            for i in range(26):
                cnt += (b & ret) > 0
                b <<= 1
            print(cnt)


if __name__ == '__main__':
    main()

Solution (Python):
import bisect

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

alphabet = [chr(ord('a') + i) for i in range(26)]

d = {alphabet[i]: [] for i in range(26)}
for i, a in enumerate(s):
    d[a].append(i)

ans = []
for i in range(q):
    query = input().split()

    if query[0] == '1':
        idx, c = int(query[1]) - 1, query[2]
        if s[idx] == c:
            continue
        d[s[idx]].remove(idx)
        bisect.insort_left(d[c], idx)
        s[idx] = c
    else:
        l, r = int(query[1]) - 1, int(query[2]) - 1
        res = 0
        for c in alphabet:
            if bisect.bisect_right(d[c], r) > bisect.bisect_left(d[c], l):
                res += 1
        ans.append(res)

for i in ans:
    print(i)

Solution (Python):
import sys,queue,math,copy,itertools,bisect,collections,heapq

def main():
    sys.setrecursionlimit(10**7)
    INF = 10**18
    MOD = 10**9 + 7
    LI = lambda : [int(x) for x in sys.stdin.readline().split()]
    NI = lambda : int(sys.stdin.readline())

    N = NI()

    R = 2**(N.bit_length())
    st = [0] * (R*2)

    def update(i,s):
        x = 2 ** (ord(s) - ord('a'))
        i += R-1
        st[i] = x
        while i > 0:
            i = (i-1) // 2
            st[i] = st[i*2+1] | st[i*2+2]

    def query(l,r):
        l += R-1
        r += R-2
        ret = 0

        while l+1 < r:
            if l % 2 == 0:
                ret |= st[l]
            if r % 2 == 1:
                ret |= st[r]
                r -= 1
            l = l // 2
            r = (r-1) // 2
        if l == r:
            ret |= st[l]
        else:
            ret |= st[l] | st[r]

        return ret

    for i,s in enumerate(sys.stdin.readline().rstrip()):
        update(i+1,s)
    Q = NI()
    for _ in range(Q):
        c,a,b = sys.stdin.readline().split()
        if c == '1':
            update(int(a),b)
        else:
            ret = query(int(a),int(b)+1)
            cnt = 0
            b = 1
            for i in range(26):
                cnt += (b & ret) > 0
                b <<= 1
            print(cnt)


if __name__ == '__main__':
    main()

Solution (Python):
def main():
  n=int(input())
  s=list(input())
  q_=int(input())
  q=[input().split() for _ in range(q_)]
  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):
      
      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)

  a2n = lambda c: ord(c) - ord('a')
  d=[BIT(n) for _ in range(26)]
  di=[0]*26
  for i in range(1,n+1):
    d[a2n(s[i-1])].add(i,1)
  for qi in q:
    if qi[0]=='1':
      i=int(qi[1])
      c=a2n(qi[2])
      si=a2n(s[i-1])
      d[c].add(i,1)
      d[si].add(i,-1)
      s[i-1]=qi[2]
    else:
      ans=0
      l,r=int(qi[1]),int(qi[2])
      for i in range(26):
        ls=d[i].sum(l-1)
        rs=d[i].sum(r)
        ans+=1 if rs-ls>0 else 0
      print(ans)
if __name__=='__main__':
  
  
  main()

Solution (Python):
import sys,queue,math,copy,itertools,bisect,collections,heapq

def main():
    sys.setrecursionlimit(10**7)
    INF = 10**18
    MOD = 10**9 + 7
    LI = lambda : [int(x) for x in sys.stdin.readline().split()]
    NI = lambda : int(sys.stdin.readline())

    N = NI()

    R = 2**(N.bit_length())
    st = [0] * (R*2)

    def update(i,s):
        x = 2 ** (ord(s) - ord('a'))
        i += R-1
        st[i] = x
        while i > 0:
            i = (i-1) // 2
            st[i] = st[i*2+1] | st[i*2+2]

    def query(a,b,n,l,r):
        ret = 0
        if a <= l and r <= b: return st[n]
        if a < r and b > l:
            vl = query(a,b,n*2+1,l,(l+r)//2)
            vr = query(a,b,n*2+2,(l+r)//2,r)
            ret = vl | vr
        return ret

    for i,s in enumerate(sys.stdin.readline().rstrip()):
        update(i+1,s)
    Q = NI()
    for _ in range(Q):
        c,a,b = sys.stdin.readline().split()
        if c == '1':
            update(int(a),b)
        else:
            ret = query(int(a),int(b)+1,0,0,R)
            cnt = 0
            b = 1
            for i in range(26):
                cnt += (b & ret) > 0
                b <<= 1
            print(cnt)


if __name__ == '__main__':
    main()

Solution (Python):
from bisect import bisect_right
from bisect import bisect_left

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

ind_list = [[] for _ in range(26)]

for i, x in enumerate(s):
    ind_list[ord(x)-97].append(i)

for _ in range(q):
    _type, val1, val2 = input().split()
    if _type == '1':
        i = int(val1)-1
        c = val2
        if s[i] == c:
            continue
        ind_list[ord(s[i])-97].remove(i)
        p = bisect_right(ind_list[ord(c)-97], i)
        ind_list[ord(c)-97].insert(p, i)
        s[i] = c
    elif _type == '2':
        l = int(val1)-1
        r = int(val2)-1
        ans = 0
        for i in range(26):
            if bisect_right(ind_list[i], r) - bisect_left(ind_list[i], l) > 0:
                ans += 1
        print(ans)
    else:
        print('Exception caught!')
        exit()

Solution (Python):
import bisect
N=input()
S=list(input())
alphabet=[[] for _ in range(26)]
for i,s in enumerate(S):
    alphabet[ord(s)-ord('a')].append(i)
Q=int(input())
for _ in range(Q):
    Type,A,B=input().split()
    if Type=="1":
        A=int(A)
        s=S[A-1]
        if s==B:
            continue
        o=ord(s)-ord("a")
        alphabet[o].pop(bisect.bisect_left(alphabet[o],A-1))
        index=bisect.bisect(alphabet[ord(B)-ord("a")],A-1)
        alphabet[ord(B)-ord("a")].insert(index,A-1)
        S[A-1]=B
    else:
        A=int(A)
        B=int(B)
        ans=0
        for i in range(26):
            indexL=bisect.bisect_left(alphabet[i],A-1)
            
            
            if indexL==len(alphabet[i]):
                continue
            ans+=(alphabet[i][indexL]<=B-1)
        print(ans)

Solution (Python):
from bisect import bisect_left

n = int(input())
s = list(input())
q = int(input())
query = [input() for _ in range(q)]

p = [[] for _ in range(26)]

for i, x in enumerate(s):
    p[ord(x) - ord('a')].append(i)

for x in query:
    a, b, c = x.split()
    
    if a == '1':
        b = int(b) - 1
        if s[b] == c:
            continue
        d = ord(s[b]) - ord('a')
        e = ord(c) - ord('a')
        temp = bisect_left(p[d], b)
        p[d].pop(temp)
        temp = bisect_left(p[e], b)
        p[e].insert(temp, b)
        s[b] = c
    else:
        b = int(b) - 1
        c = int(c) - 1
        
        ans = 0
        for i in range(26):
            L = bisect_left(p[i], b)
            if L >= len(p[i]):
                continue
            if p[i][L] <= c:
                ans += 1
        print(ans)

Solution (Python):
n = int(input())
S = list(input())
q = int(input())

import sys
input = sys.stdin.readline

alp = "abcdefghijklmnopqrstuvwxyz"
appr = {a:[] for a in alp}

import bisect

for i, a in enumerate(S):
  appr[a].append(i+1)

for i in range(q):
  inputs = input().split()
  if inputs[0] == '1':
    c = int(inputs[1])
    a = inputs[2]
    if S[c-1]==a:
      continue
    else:
      old = S[c-1]
      S[c-1] = a
      del_idx = bisect.bisect_left(appr[old], c)
      del appr[old][del_idx]
      in_idx = bisect.bisect_left(appr[a], c)
      appr[a].insert(in_idx, c)
  else:
    l, r = map(int, inputs[1:])
    res = 0
    for a in appr:
      l_idx = bisect.bisect_left(appr[a], l)
      if l_idx<len(appr[a]):
        if appr[a][l_idx]<=r:
          res += 1
    print(res)