Language: C++

#include <iostream>
#include <fstream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <bitset>
#include <algorithm>
#include <complex>
#include <array>
#include <iomanip>

using namespace std;

#define REP(i,n) for(int i=0; i<n; ++i)
#define FOR(i,a,b) for(int i=a; i<=b; ++i)
#define FORR(i,a,b) for (int i=a; i>=b; --i)
#define ALL(c) (c).begin(), (c).end()

typedef long long ll;
typedef vector<int> VI;
typedef vector<ll> VL;
typedef vector<long double> VD;
typedef vector<VI> VVI;
typedef vector<VL> VVL;
typedef vector<VD> VVD;
typedef pair<int,int> P;
typedef pair<ll,ll> PL;

template<typename T> void chmin(T &a, T b) { if (a > b) a = b; }
template<typename T> void chmax(T &a, T b) { if (a < b) a = b; }

int in() { int x; scanf("%d", &x); return x; }
ll lin() { ll x; scanf("%lld", &x); return x; }
#define INF 1LL<<60

vector< set<char> > value; // ノードの値を持つ配列
int N;             // 葉の数
 
void update(int i, char x) {
    // i 番目の葉の値を x に変える
    i += N - 1; // i 番目の葉のノード番号
    value[i] = { x };
    while (i > 0) {
        i = (i - 1) / 2; // ノード i の親ノードの番号に変える
        // value[i] = min(value[i * 2 + 1],
                    //    value[i * 2 + 2]); // 左右の子の min を計算しなおす
        set<char> result;
        set_union(value[i * 2 + 1].begin(), value[i * 2 + 1].end(),
                    value[i * 2 + 2].begin(), value[i * 2 + 2].end(),
                    inserter(result, result.end()));
        value[i] = result;
    }
}
 
set<char> query(int a, int b, int k, int l, int r) {
    // [a, b) の区間に対するクエリについて
    // ノード k （区間 [l, r) 担当）が答える
    if (r <= a || b <= l) return {}; // 区間が被らない場合は INF を返す
    if (a <= l && r <= b)
        return value[k]; // ノード k の担当範囲がクエリ区間 [a, b)
                         // に完全に含まれる
    else {
        set<char> c1 = query(a, b, 2 * k + 1, l, (l + r) / 2); // 左の子に値を聞く
        set<char> c2 = query(a, b, 2 * k + 2, (l + r) / 2, r); // 右の子に値を聞く
        set<char> result;
        set_union(c1.begin(), c1.end(), c2.begin(), c2.end(),
            inserter(result, result.end())); // 左右の子の値の min を取る
        return result;
    }
}

int main() {
    int Q;
    string S;
    cin >> N;
    cin >> S;
    cin >> Q;

    vector<int> QType(Q), I(Q), L(Q), R(Q);
    vector<char> C(Q);
    REP(i, Q) {
        int query_type;
        cin >> query_type;
        QType[i] = query_type;
        if(query_type==1) {
            cin >> I[i] >> C[i];
        } else {
            cin >> L[i] >> R[i];
        }
    }

    value = vector< set<char> >(2*N-1, {});
    REP(i, N) {
        update(i, S[i]);
    }

    REP(i, Q) {
        if(QType[i] == 1) {
            update(I[i]-1, C[i]);
        } else {
            set<char> result = query(L[i]
            , R[i]+1, 0, 0, N-1);
            cout << result.size() << endl;
        }
    }
    
    return 0;
}

Compiler output:
a.cc: In function 'int main()':
a.cc:98:42: error: call of overloaded 'vector(int, <brace-enclosed initializer list>)' is ambiguous
   98 |     value = vector< set<char> >(2*N-1, {});
      |                                          ^
In file included from /usr/include/c++/14/vector:66,
                 from a.cc:5:
/usr/include/c++/14/bits/stl_vector.h:569:7: note: candidate: 'std::vector<_Tp, _Alloc>::vector(size_type, const value_type&, const allocator_type&) [with _Tp = std::set<char>; _Alloc = std::allocator<std::set<char> >; size_type = long unsigned int; value_type = std::set<char>; allocator_type = std::allocator<std::set<char> >]'
  569 |       vector(size_type __n, const value_type& __value,
      |       ^~~~~~
/usr/include/c++/14/bits/stl_vector.h:556:7: note: candidate: 'std::vector<_Tp, _Alloc>::vector(size_type, const allocator_type&) [with _Tp = std::set<char>; _Alloc = std::allocator<std::set<char> >; size_type = long unsigned int; allocator_type = std::allocator<std::set<char> >]'
  556 |       vector(size_type __n, const allocator_type& __a = allocator_type())
      |       ^~~~~~