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.



Sample input:
7
abcdbbd
6
2 3 6
1 5 z
2 1 1
1 4 a
1 7 d
2 1 7


Sample output:
3
1
5

Submission status: Accepted

Solution code:
# Reference: https://qiita.com/dn6049949/items/afa12d5d079f518de368

# self.data: 1-indexed
#    __1__
#  _2_   _3_
# 4   5 6   7

# f(f(a, b), c) == f(a, f(b, c))

class SegmentTree:
    # a = [default] * n
    # O(n)
    def __init__(self, n, f=max, default=-2**30):
        self.num_leaf = 2 ** (n-1).bit_length()
        self.data = [default] * (2*self.num_leaf)
        self.f = f

    # a[i] = x
    # O(log(n))
    def update(self, i, x):
        i += self.num_leaf
        self.data[i] = x
        i >>= 1
        while i > 0:
            self.data[i] = self.f(self.data[2*i], self.data[2*i+1])
            i >>= 1

    # return f(a[l:r])
    # O(log(n))
    def query(self, l, r):
        l += self.num_leaf
        r += self.num_leaf - 1
        lres, rres = self.data[0], self.data[0] # self.data[0] == default
        while l < r:
            if l & 1:
                lres = self.f(lres, self.data[l])
                l += 1
            if not r & 1:
                rres = self.f(self.data[r], rres)
                r -= 1
            l >>= 1
            r >>= 1
        if l == r:
            res = self.f(self.f(lres, self.data[l]), rres)
        else:
            res = self.f(lres, rres)
        return res

    # You can use min_index only if f == max.
    # return min({i | x <= i and v <= a[i]}, self.num_leaf)
    # O(log(n))
    def min_index(self, x, v):
        x += self.num_leaf
        while self.data[x] < v:
            if x & 1:
                if x.bit_length() == (x+1).bit_length():
                    x += 1
                else:
                    return self.num_leaf
            else:
                x >>= 1
        while x < self.num_leaf:
            if self.data[2*x] >= v:
                x = 2*x
            else:
                x = 2*x + 1
        return x - self.num_leaf

from sys import stdin
def input():
    return stdin.readline().strip()

def main():
    n = int(input())
    s = list(input())

    forest = [SegmentTree(n, f=max, default=0) for _ in range(26)]
    for ind, si in enumerate(s):
        forest[ord(si) - 97].update(ind, 1)

    q = int(input())
    ans = []
    for _ in range(q):
        typ, l, r = input().split()
        l = int(l) - 1

        if typ == '1':
            forest[ord(s[l]) - 97].update(l, 0)
            s[l] = r
            forest[ord(r) - 97].update(l, 1)

        else:
            cnt = 0
            for tree in forest:
                if tree.min_index(l, 1) < int(r):
                    cnt += 1
            ans.append(cnt)

    for i in ans:
        print(i)

main()

Submission status: Accepted

Solution code:
# Reference: https://qiita.com/dn6049949/items/afa12d5d079f518de368

# self.data: 1-indexed
#    __1__
#  _2_   _3_
# 4   5 6   7

# f(f(a, b), c) == f(a, f(b, c))

class SegmentTree:
    # a = [default] * n
    # O(n)
    def __init__(self, n, f=max, default=-2**30):
        self.num_leaf = 2 ** (n-1).bit_length()
        self.data = [default] * (2*self.num_leaf)
        self.f = f

    # a[i] = x
    # O(log(n))
    def update(self, i, x):
        i += self.num_leaf
        self.data[i] = x
        i >>= 1
        while i > 0:
            self.data[i] = self.f(self.data[2*i], self.data[2*i+1])
            i >>= 1

    # return f(a[l:r])
    # O(log(n))
    def query(self, l, r):
        l += self.num_leaf
        r += self.num_leaf - 1
        lres, rres = self.data[0], self.data[0] # self.data[0] == default
        while l < r:
            if l & 1:
                lres = self.f(lres, self.data[l])
                l += 1
            if not r & 1:
                rres = self.f(self.data[r], rres)
                r -= 1
            l >>= 1
            r >>= 1
        if l == r:
            res = self.f(self.f(lres, self.data[l]), rres)
        else:
            res = self.f(lres, rres)
        return res

    # You can use min_index only if f == max.
    # return min({i | x <= i and v <= a[i]}, self.num_leaf)
    # O(log(n))
    def min_index(self, x, v):
        x += self.num_leaf
        while self.data[x] < v:
            if x & 1:
                if x.bit_length() == (x+1).bit_length():
                    x += 1
                else:
                    return self.num_leaf
            else:
                x >>= 1
        while x < self.num_leaf:
            if self.data[2*x] >= v:
                x = 2*x
            else:
                x = 2*x + 1
        return x - self.num_leaf

from sys import stdin
def input():
    return stdin.readline().strip()

def main():
    n = int(input())
    s = list(input())

    forest = [SegmentTree(n, f=max, default=0) for _ in range(26)]
    for ind, si in enumerate(s):
        forest[ord(si) - 97].update(ind, 1)

    q = int(input())
    ans = []
    for _ in range(q):
        typ, l, r = input().split()
        l = int(l) - 1

        if typ == '1':
            forest[ord(s[l]) - 97].update(l, 0)
            s[l] = r
            forest[ord(r) - 97].update(l, 1)

        else:
            cnt = 0
            for tree in forest:
                if tree.query(l, int(r)) == 1:
                    cnt += 1
            ans.append(cnt)

    for i in ans:
        print(i)

main()

Submission status: Accepted

Solution code:
#!/usr/bin python3
# -*- coding: utf-8 -*-

from bisect import bisect_left, bisect_right


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

al = 'abcdefghijklmnopqrstuvwxyz'
dicq = {i:[] for i in al}
for i, si in enumerate(s):
    dicq[si].append(i)

def q1(iq, cq):
    #print(iq,cq,s[iq],dicq[s[iq]],bisect_left(dicq[s[iq]], iq))
    dicq[s[iq]].pop(bisect_left(dicq[s[iq]], iq))   #更新前から削除
    s[iq] = cq
    dicq[cq].insert(bisect_left(dicq[cq], iq), iq)   #更新後に追加

def q2(l, r):
    ret = 0
    for ai in al:
        if len(dicq[ai])==0: continue
        li = bisect_left(dicq[ai], l)
        ri = bisect_right(dicq[ai], r)
        if li != ri:
            ret += 1
        elif li == len(dicq[ai]): continue
        elif dicq[ai][li] == l:
            ret += 1
    #    print(l,r,ai,dicq[ai],li,ri,ret)
    print(ret)

for i in range(q):
    fg, x, y = input().split()
    if fg == '1':
        q1(int(x)-1, y)
    else:
        q2(int(x)-1, int(y)-1)

Submission status: Accepted

Solution code:
n = int(input())
s = list(input())
BITs = [[0]*(n+1) for _ in range(26)]

def c_idx(c):
    return ord(c) - 97

def query(pos):
    ret = [0]*26
    for i in range(26):
        tmp = 0
        p = pos
        while p > 0:
            tmp += BITs[i][p]
            p -= p & (-p)
        ret[i] = tmp
    return ret

def update(pos, a, x):
    while pos <= n:
        BITs[a][pos] += x
        pos += pos & (-pos)

for i in range(n):
    update(i+1, c_idx(s[i]), 1)
#print(BITs)

q = int(input())
for _ in range(q):
    a, b, c = input().split()
    b = int(b)
    if a == "1":
        if s[b-1] == c:
            continue
        update(b, c_idx(s[b-1]), -1)
        update(b, c_idx(c), 1)
        s[b-1] = c
    else:
        c = int(c)
        count1 = query(c)
        count2 = query(b-1)
        ans = 0
        for i in range(26):
            if count1[i] - count2[i] > 0:
                ans += 1
        print(ans)

Submission status: Accepted

Solution code:
import bisect, collections, copy, heapq, itertools, math, string
import sys
def I(): return int(sys.stdin.readline().rstrip())
def MI(): return map(int, sys.stdin.readline().rstrip().split())
def LI(): return list(map(int, sys.stdin.readline().rstrip().split()))
def S(): return sys.stdin.readline().rstrip()
def LS(): return list(sys.stdin.readline().rstrip().split())

from  collections import defaultdict
import bisect


# SegTreeの関数
def segfunc(x, y):
    return x | y


# 単位元
# min->inf, max->-inf, add->0, mul->1
ide_ele = set()


# セグメント木
class SegTree:
    """
    init(init_val, segfunc, ide_ele): 配列init_valで初期化、構築
    update(k, x): k番目の値をxに更新
    query(l, r): 区間[l, r)をsegfuncしたものを返す
    """

    def __init__(self, init_val, segfunc, ide_ele):
        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に更新
        :param k: index(0-index)
        :param 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したものを得る
        :param l: 0-index
        :param r: 0-index
        :return:
        """
        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

def main():
    N = I()
    S_ = S()
    S_list = []
    Q = I()
    for s in S_:
        val = set()
        val.add(s)
        S_list.append(val)


    segtree = SegTree(S_list, segfunc, ide_ele)
    for i in range(Q):
        query = LS()
        if query[0] == '1':
            i_q = int(query[1]) - 1
            c_q = query[2]
            segtree.update(i_q, {c_q})
        if query[0] == '2':
            l_q = int(query[1]) - 1
            r_q = int(query[2])
            ans = len(segtree.query(l_q, r_q))
            print(ans)

if __name__ == "__main__":
    main()

Submission status: Accepted

Solution code:
class SegTree:
    """ segment tree with point modification and range product. """
    # # https://yukicoder.me/submissions/452850
    def __init__(self, N, data_f = min, data_unit=1<<30):
        self.N = N
        self.data_f = data_f
        self.data_unit = data_unit
        self.data = [self.data_unit] * (N + N)

    def build(self, raw_data):
        data = self.data
        f = self.data_f
        N = self.N
        data[N:] = raw_data[:]
        for i in range(N - 1, 0, -1):
            data[i] = f(data[i << 1], data[i << 1 | 1])

    def set_val(self, i, x):
        data = self.data
        f = self.data_f
        i += self.N
        data[i] = x
        while i > 1:
            data[i >> 1] = f(data[i], data[i ^ 1])
            i >>= 1

    def fold(self, L, R):
        """ compute for [L, R) """
        vL = vR = self.data_unit
        data = self.data
        f = self.data_f
        L += self.N
        R += self.N
        while L < R:
            if L & 1:
                vL = f(vL, data[L])
                L += 1
            if R & 1:
                R -= 1
                vR = f(data[R], vR)
            L >>= 1
            R >>= 1
        return f(vL, vR)
      
N=int(input())
S=input()
seg = SegTree(N,set.union,set())
S = [set([ord(S[i])-97]) for i in range(N)]
seg.build(S)
Q=int(input())
for i in range(Q):
  *q, = input().split()
  if q[0] == '1':
    i, c = q[1:]
    seg.set_val(int(i)-1,set([ord(c)-97]))
  else:
    l,r = map(int,q[1:])
    print(len(seg.fold(l-1,r)))

Submission status: Accepted

Solution code:
class SegTree:
    """ segment tree with point modification and range product. """
    # # https://yukicoder.me/submissions/452850
    def __init__(self, N, data_f = min, data_unit=1<<30):
        self.N = N
        self.data_f = data_f
        self.data_unit = data_unit
        self.data = [self.data_unit] * (N + N)

    def build(self, raw_data):
        data = self.data
        f = self.data_f
        N = self.N
        data[N:] = raw_data[:]
        for i in range(N - 1, 0, -1):
            data[i] = f(data[i << 1], data[i << 1 | 1])

    def set_val(self, i, x):
        data = self.data
        f = self.data_f
        i += self.N
        data[i] = x
        while i > 1:
            data[i >> 1] = f(data[i], data[i ^ 1])
            i >>= 1

    def fold(self, L, R):
        """ compute for [L, R) """
        vL = vR = self.data_unit
        data = self.data
        f = self.data_f
        L += self.N
        R += self.N
        while L < R:
            if L & 1:
                vL = f(vL, data[L])
                L += 1
            if R & 1:
                R -= 1
                vR = f(data[R], vR)
            L >>= 1
            R >>= 1
        return f(vL, vR)
      
N=int(input())
S=input()
data = [[0]*N for _ in range(26)]
di = {}
for i in range(N):
  data[ord(S[i])-97][i] = 1
  di[i] = S[i]

seg = [SegTree(N,max,0) for _ in range(26)]
for i in range(26):
  seg[i].build(data[i])
Q=int(input())
for i in range(Q):
  *q, = input().split()
  if q[0] == '1':
    i, c = q[1:]
    i = int(i)-1
    c_old = di[i]
    di[i] = c
    seg[ord(c_old)-97].set_val(i,0)
    seg[ord(c)-97].set_val(i,1)
  else:
    l,r = map(int,q[1:])
    ans=0
    for i in range(26):
      ans += seg[i].fold(l-1,r)
    print(ans)

Submission status: Accepted

Solution code:
class SegTree:
    """ segment tree with point modification and range product. """
    # # https://yukicoder.me/submissions/452850
    def __init__(self, N, data_f = min, data_unit=1<<30):
        self.N = N
        self.data_f = data_f
        self.data_unit = data_unit
        self.data = [self.data_unit] * (N + N)

    def build(self, raw_data):
        data = self.data
        f = self.data_f
        N = self.N
        data[N:] = raw_data[:]
        for i in range(N - 1, 0, -1):
            data[i] = f(data[i << 1], data[i << 1 | 1])

    def set_val(self, i, x):
        data = self.data
        f = self.data_f
        i += self.N
        data[i] = x
        while i > 1:
            data[i >> 1] = f(data[i], data[i ^ 1])
            i >>= 1

    def fold(self, L, R):
        """ compute for [L, R) """
        vL = vR = self.data_unit
        data = self.data
        f = self.data_f
        L += self.N
        R += self.N
        while L < R:
            if L & 1:
                vL = f(vL, data[L])
                L += 1
            if R & 1:
                R -= 1
                vR = f(data[R], vR)
            L >>= 1
            R >>= 1
        return f(vL, vR)
      
N=int(input())
S=input()
seg = SegTree(N,set.union,set())
S = [set(S[i]) for i in range(N)]
seg.build(S)
Q=int(input())
for i in range(Q):
  *q, = input().split()
  if q[0] == '1':
    i, c = q[1:]
    seg.set_val(int(i)-1,set(c))
  else:
    l,r = map(int,q[1:])
    print(len(seg.fold(l-1,r)))

Submission status: Accepted

Solution code:
class SegmentTree: #1-indexed
    def __init__(self,list,a,f=lambda x,y:x+y,inf=0):
        self.height=(len(list)-1).bit_length()+1 #木の高さ
        self.id=inf #単位元
        self.tree=[self.id]*(2**self.height) #木を単位元で初期化
        self.f=f
        for i in range(len(list)):
            if list[i]==a:
                self.tree[2**(self.height-1)+i]=1
        for i in range(2**(self.height-1)-1,0,-1):
            self.tree[i]=self.f(self.tree[2*i],self.tree[2*i+1])
        
    def update(self,i,x): #i番目の要素をxに変更(0-indexed)
        i+=2**(self.height-1)
        self.tree[i]=x
        while i>1:
            i//=2
            self.tree[i]=self.f(self.tree[2*i],self.tree[2*i+1])
    
    def query(self,l,r): #0-indexed
        l+=2**(self.height-1)
        r+=2**(self.height-1)
        lf,rf=self.id,self.id
        while l<r:
            if l&1:
                lf=self.f(lf,self.tree[l])
                l+=1
            if r&1:
                r-=1
                rf=self.f(self.tree[r],rf)
            l//=2
            r//=2
        return self.f(lf,rf)
n=int(input())
s=list(input())
q=int(input())
l=[]
for i in range(26):
    l.append(SegmentTree(s,chr(97+i),f=lambda x,y:x or y))
for _ in range(q):
    a,b,c=input().split()
    if a=="1":
        b=int(b)-1
        l[ord(s[b])-97].update(b,0)
        l[ord(c)-97].update(b,1)
        s[b]=c
    else:
        b,c=int(b)-1,int(c)
        count=0
        for i in range(26):
            if l[i].query(b,c):
                count+=1
        print(count)

Submission status: Accepted

Solution code:
def segfunc(x,y):
  return set(x)|set(y)
ide_ele=set()
class SegTree():
  def __init__(self,init_val,segfunc,ide_ele):
    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+=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):
    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())
st=SegTree(s,segfunc,ide_ele)
for _ in range(q):
  q,c,r=input().split()
  if q=='1':st.update(int(c)-1,r)
  else:print(len(st.query(int(c)-1,int(r))))

Submission status: Accepted

Solution code:
"""
セグメント木で行きたいところだけど、集合の管理が必要になるため、時間がかかりすぎてしまう。
と思いきや、文字の種類は26種類しかないので、問題ない。
"""
def main():
    import sys
    input = sys.stdin.readline
    from collections import Counter
    class BIT:
        def __init__(self,n):
            self.size = n
            self.tree = [Counter([]) for _ in range(n+1)]
        
        def change(self,i,x,y):
            while i <= self.size:
                if x in self.tree[i]:
                    self.tree[i][x] -= 1
                if y not in self.tree[i]:
                    self.tree[i][y] = 1
                else:
                    self.tree[i][y] += 1
                i += i&-i
    
        def sum(self,i):
            s = Counter([])
            while i > 0:
                s += self.tree[i]
                i -= i&-i
            cnt = 0
            return s


    N = int(input())
    S = list(input())
    Q = int(input())
    bit = BIT(N)
    for i in range(N):
        bit.change(i+1," ",S[i])

    for _ in range(Q):
        q,a,b = input().split()
        if q == "1":
            x = S[int(a)-1]
            S[int(a)-1] = b
            bit.change(int(a),x,b)
        else:
            a = int(a)
            b = int(b)
            count = bit.sum(b) - bit.sum(a-1)
            ans = 0
            for v in count.values():
                if v > 0:
                    ans += 1
            print(ans)
main()

Submission status: Accepted

Solution code:
N = int(input())
S = list(input())
Q = int(input())
alphabet = "abcdefghijklmnopqrstuvwxyz"
num = dict()
for i, var in enumerate(alphabet):
  num[var] = i

class Bit():
  def __init__(self, N):
    self.__N = N
    self.__arr = [[0] * 26 for _ in range(1 + N)]
    
  def add_(self, x, a, i):
    while(x < self.__N + 1):
      self.__arr[x][i] += a
      x += x & -x
      
  def sum_(self, x, i):
    res = 0
    while(x > 0):
      res += self.__arr[x][i]
      x -= x & -x
    return res
  
  def sub_sum_(self, x, y, i):
    return self.sum_(y, i) - self.sum_(x, i)

Bit = Bit(N)
for i, var in enumerate(S):
  Bit.add_(i+1, 1, num[var])

for i in range(Q):
  q, l, r = input().split()
  l = int(l)
  if q == "1" and r != S[l-1]:
    temp = S[l-1]
    S[l-1] = r
    Bit.add_(l, -1, num[temp])
    Bit.add_(l, 1, num[r])
  elif q == "2":
    r = int(r)
    res = 0
    for j in range(26):
      res += min(1, Bit.sub_sum_(l-1, r, j))
    print(res)

Submission status: Accepted

Solution code:
# E - Simple String Queries

class FenwickTree():
    
    # インデックスは1-start
    # 初期化
    def __init__(self, n):
        self.n = n
        self.data = [0]*(n+1)
        self.el = [0]*(n+1)
    
    # private function
    def summation(self, i):
        s = 0
        while i > 0:
            s += self.data[i]
            i -= i & -i
        return s
    
    # i番目の要素にxを加える（初期値 0）
    def add(self, i, x):
        self.el[i] += x
        while i <= self.n:
            self.data[i] += x
            i += i & -i
    
    # i番目の要素 or [i,j]の要素和を取得
    def get(self, i, j=None):
        if j is None:
            return self.el[i]
        return self.summation(j) - self.summation(i-1)

N = int(input())
S_raw = input()
S = [0]*(N+1)
trees = [FenwickTree(N) for _ in range(26)]
for i in range(1,N+1):
    s = S_raw[i-1]
    S[i] = s
    k = ord(s)-ord('a')
    trees[k].add(i, 1)

Q = int(input())
for _ in range(Q):
    q,x,y = input().split()
    if q=='1':
        i,c = int(x),y
        s = S[i]
        k = ord(s)-ord('a')
        trees[k].add(i, -1)
        S[i] = c
        k = ord(c)-ord('a')
        trees[k].add(i, 1)
    else:
        l,r = int(x),int(y)
        ans = 0
        for k in range(26):
            ans = ans+1 if trees[k].get(l,r)>0 else ans
        print(ans)

Submission status: Accepted

Solution code:
import bisect
from collections import defaultdict

N = int(input())
# 書き換える時に文字列だと不便なのでリスト化しておく
S = list(input())
Q = int(input())

dict = defaultdict(list)
for i in range(N):
    dict[S[i]].append(i)
# print(dict)

ans = []

for _ in range(Q):
    a, b, c = input().split()
    a = int(a)

    if a == 1:
        b = int(b) - 1
        if S[b] == c:
            continue
        else:
            dict[S[b]].remove(b)
            idx = bisect.bisect_left(dict[c], b)
            dict[c].insert(idx, b)
            S[b] = c

    elif a == 2:
        b = int(b) - 1
        c = int(c) - 1
        char_n = 0
        for key, value in dict.items():
            x1 = bisect.bisect_left(value, b)
            x2 = bisect.bisect_right(value, c)
            if x2 - x1 > 0:
                char_n += 1
        ans.append(char_n)

for i in ans:
    print(i)

Submission status: Accepted

Solution code:
import bisect
from collections import defaultdict
N = int(input())
S = list(input())
Q = int(input())

dict = defaultdict(list)
for i in range(N):
    dict[S[i]].append(i)
# print(dict)

ans = []

for _ in range(Q):
    a, b, c = input().split()
    a = int(a)

    if a == 1:
        b = int(b) - 1
        if S[b] == c:
            continue
        else:
            dict[S[b]].remove(b)
            idx = bisect.bisect_left(dict[c], b)
            dict[c].insert(idx, b)
            S[b] = c

    elif a == 2:
        b = int(b) - 1
        c = int(c) - 1
        char_n = 0
        for key, value in dict.items():
            if len(value)>0:
                x1 = bisect.bisect_left(value, b)
                x2 = bisect.bisect_right(value, c)
                if x2 - x1 > 0:
                    char_n += 1
        ans.append(char_n)

for i in ans:
    print(i)

Submission status: Accepted

Solution code:
# test!!!!!!!!!!!

from bisect import bisect_left, bisect_right

N = int(input())

S = list(input())

Q = int(input())

# {"a":[], "b":[], ..., "z":[]}
dict = {chr(ord('a') + i): [] for i in range(26)}


for i in range(N):
    dict[S[i]].append(i)

ans = []

for q in range(Q):
    query = list(input().split())
    if query[0] == '1':
        i, x = int(query[1])-1, query[2]
        now = S[i]
        if now == x:
            continue
        dict[now].remove(i)
        next_i = bisect_left(dict[x], i)
        dict[x].insert(next_i, i)
        S[i] = x
    else:
        start, end = int(query[1])-1, int(query[2])-1
        tmp_cout = 0
        for alf_array in dict.values():
            if len(alf_array) == 0:
                continue
            ss = bisect_left(alf_array, start)
            gg = bisect_right(alf_array, end)
            if gg- ss > 0:
                tmp_cout += 1
        ans.append(tmp_cout)

for i in ans:
    print(i)

Submission status: Accepted

Solution code:
# test!!!!!!!!!!!

from bisect import bisect_left, bisect_right

N = int(input())

S = list(input())

Q = int(input())

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

for key,val in enumerate(S):
    memo[val].append(key)

for q in range(Q):
    query = list(input().split())
    if query[0] == '1':
        i, x = int(query[1])-1, query[2]
        now = S[i]
        if now == x:
            continue
        memo[now].remove(i)
        next_i = bisect_left(memo[x], i)
        memo[x].insert(next_i, i)
        S[i] = x
    else:
        start, end = int(query[1])-1, int(query[2])-1
        tmp_cout = 0
        for alf_array in memo.values():
            if len(alf_array) == 0:
                continue
            ss = bisect_left(alf_array, start)
            gg = bisect_right(alf_array, end)
            if gg- ss > 0:
                tmp_cout += 1
        print(tmp_cout)

Submission status: Accepted

Solution code:
import sys

read = sys.stdin.read
readline = sys.stdin.readline
readlines = sys.stdin.readlines
sys.setrecursionlimit(10 ** 9)
INF = 1 << 60
MOD = 1000000007


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

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

    def get_sum(self, i):
        i += 1
        x = 0
        while i > 0:
            x += self.data[i]
            i -= i & -i
        return x

    # Return sum for [l, r)
    def get_sum_range(self, l, r):
        return self.get_sum(r - 1) - self.get_sum(l - 1)


def main():
    N = int(readline())
    S = readline().strip()
    Q = int(readline())

    S = list(S)

    tree = [BIT(N) for _ in range(26)]
    for i, c in enumerate(S):
        tree[ord(c) - ord('a')].add(i)

    ans = []
    for _ in range(Q):
        A = readline().split()
        if A[0] == '1':
            i, c = int(A[1]) - 1, A[2]
            if S[i] != c:
                tree[ord(S[i]) - ord('a')].add(i, -1)
                tree[ord(A[2]) - ord('a')].add(i, 1)
                S[i] = c
        else:
            l, r = int(A[1]) - 1, int(A[2]) - 1
            tmp = 0
            for i in range(26):
                if tree[i].get_sum_range(l, r + 1) > 0:
                    tmp += 1
            ans.append(tmp)

    print('\n'.join(map(str, ans)))
    return


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
import sys
input = sys.stdin.readline
N = int(input())
S = list(map(lambda x: ord(x) - ord("a"), list(input())[: -1]))

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)
  def lowerbound(self, s):
    x = 0
    y = 0
    for i in range(self.n.bit_length(), -1, -1):
      k = x + (1 << i)
      if k <= self.n and (y + self.data[k] < s):
        y += self.data[k]
        x += 1 << i
    return x + 1

fwk = [BIT(N) for _ in range(26)]
for i in range(N): fwk[S[i]].add(i + 1, 1)
for _ in range(int(input())):
  q, x, y = input().split()
  if q == "1":
    x = int(x)
    y = ord(y) - ord("a")
    fwk[S[x - 1]].add(x, -1)
    fwk[y].add(x, 1)
    S[x - 1] = y
  else:
    x = int(x)
    y = int(y)
    res = 0
    for i in range(26): res += fwk[i].get(x - 1, y) > 0
    print(res)

Submission status: Accepted

Solution code:
#!/usr/bin/env python3
import sys
sys.setrecursionlimit(10**6)

# Segment Tree
class SegmentTree:
    def __init__(self, N):
        self.size = 2 ** (N-1).bit_length()# 要素数を超える最小の2べき
        self.dat = [0] * (2*self.size)
    
    def update(self,i,x):# i番目の文字がxになる
        i += self.size
        self.dat[i] = 1 << ord(x)-ord('a')
        while i > 0:# 上まで更新していく
            i >>= 1
            self.dat[i] = self.dat[i*2] | self.dat[i*2+1]

    def fold(self, l, r):
        l += self.size
        r += self.size
        vl = 0
        vr = 0
        while l < r:
            if l & 1:
                vl |= self.dat[l]
                l += 1
            if r & 1:
                r -= 1
                vr |= self.dat[r]
            l >>= 1
            r >>= 1
        # print(bin(vl | vr))
        return bin(vl | vr).count('1')

def main():
    N = int(input())
    S = list(input())
    sg = SegmentTree(N)
    for i in range(N):
        sg.update(i,S[i])
    
    Q = int(input())
    for _ in range(Q):
        Query = input().split()
        if Query[0] == '1':
            sg.update(int(Query[1])-1, Query[2])
        else:
            res = sg.fold(int(Query[1])-1, int(Query[2]))
            print(res)

if __name__ == "__main__":
    main()

Submission status: Accepted

Solution code:
from bisect import bisect_left, bisect_right

N = int(input())

S = list(input())

Q = int(input())

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

for key,val in enumerate(S):
    memo[val].append(key)

for q in range(Q):
    query = list(input().split())
    if query[0] == '1':
        i, x = int(query[1])-1, query[2]
        now = S[i]
        if now == x:
            continue
        memo[now].remove(i)
        next_i = bisect_left(memo[x], i)
        memo[x].insert(next_i, i)
        S[i] = x
    else:
        start, end = int(query[1])-1, int(query[2])-1
        tmp_cout = 0
        for alf_array in memo.values():
            if len(alf_array) == 0:
                continue
            ss = bisect_left(alf_array, start)
            gg = bisect_right(alf_array, end)
            if gg- ss > 0:
                tmp_cout += 1
        print(tmp_cout)