#include <algorithm>
#include <bits/stdc++.h>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <iostream>
#include <iterator>
#include <type_traits>
#include <vector>

// lib/ceil_log2.hpp
#ifndef CEIL_LOG2_HPP
#define CEIL_LOG2_HPP


namespace tools {
  ::std::uint32_t ceil_log2(::std::uint32_t x);
  ::std::uint64_t ceil_log2(::std::uint64_t x);
  ::std::int32_t ceil_log2(::std::int32_t x);
  ::std::int64_t ceil_log2(::std::int64_t x);
}

#endif

// lib/pow2.hpp
#ifndef POW2_HPP
#define POW2_HPP

/*
usage:

tools::pow2(5) => 32
*/


namespace tools {
  template <typename T, typename std::enable_if<std::is_unsigned<T>::value, std::nullptr_t>::type = nullptr>
  constexpr T pow2(const T x) {
    return static_cast<T>(1) << x;
  }

  template <typename T, typename std::enable_if<std::is_signed<T>::value, std::nullptr_t>::type = nullptr>
  constexpr T pow2(const T x) {
    return static_cast<T>(static_cast<typename std::make_unsigned<T>::type>(1) << static_cast<typename std::make_unsigned<T>::type>(x));
  }
}

#endif

// lib/monoid.hpp
#ifndef MONOID_HPP
#define MONOID_HPP


namespace tools {
  template <typename T>
  class monoid {
  private:
    ::std::function<T(T, T)> m_operation;
    T m_identity;

  public:
    monoid(const ::std::function<T(T, T)>& operation, const T& identity) :
      m_operation(operation),
      m_identity(identity) {
    }
    monoid(const ::tools::monoid<T>&) = default;
    monoid(::tools::monoid<T>&&) = default;
    ::tools::monoid<T>& operator=(const ::tools::monoid<T>&) = default;
    ::tools::monoid<T>& operator=(::tools::monoid<T>&&) = default;
    virtual ~monoid() = default;

    T operation(const T& x, const T& y) const {
      return this->m_operation(x, y);
    }
    const T& identity() const {
      return this->m_identity;
    }

    template <typename U = T, typename ::std::enable_if<::std::is_integral<U>::value, ::std::nullptr_t>::type = nullptr>
    static ::tools::monoid<U> multiplies() {
      return ::tools::monoid<U>(::std::multiplies<U>(), 1);
    }
  };
}

#endif

// lib/util.hpp
#ifndef UTIL_HPP
#define UTIL_HPP


typedef ::std::int_fast64_t i64;
typedef ::std::uint_fast64_t u64;
typedef ::std::int_fast32_t i32;
typedef ::std::uint_fast32_t u32;

namespace tools {
  template <typename T>
  void read(::std::istream& is, ::std::vector<T>& vector, const typename ::std::vector<T>::size_type size) {
    vector.reserve(size);
    ::std::copy_n(::std::istream_iterator<T>(is), size, ::std::back_inserter(vector));
  }
  template <typename T>
  void read(::std::vector<T>& vector, const typename ::std::vector<T>::size_type size) {
    ::tools::read(::std::cin, vector, size);
  }

  template <typename T, ::std::size_t N>
  void read(::std::istream& is, ::std::array<T, N>& array) {
    ::std::copy_n(std::istream_iterator<T>(is), N, array.begin());
  }
  template <typename T, ::std::size_t N>
  void read(::std::array<T, N>& array) {
    ::tools::read(::std::cin, array);
  }
}

#endif

// lib/ceil_log2.cpp

// Source: Stack Overflow ( https://stackoverflow.com/questions/3272424/compute-fast-log-base-2-ceiling/15327567#15327567 )
// Author: dgobbi ( https://stackoverflow.com/users/2154690/dgobbi )
// License: CC BY-SA 3.0
namespace tools {
  std::uint32_t ceil_log2(std::uint32_t x) {
    static const ::std::uint32_t t[6] = {
      0xFFFF0000u,
      0x0000FF00u,
      0x000000F0u,
      0x0000000Cu,
      0x00000002u
    };

    ::std::uint32_t y = (((x & (x - 1)) == 0) ? 0 : 1);
    ::std::uint32_t j = 16;

    for (const ::std::uint32_t& t_i : t) {
      ::std::uint32_t k = (((x & t_i) == 0) ? 0 : j);
      y += k;
      x >>= k;
      j >>= 1;
    }

    return y;
  }

  ::std::uint64_t ceil_log2(::std::uint64_t x) {
    static const ::std::uint64_t t[6] = {
      0xFFFFFFFF00000000u,
      0x00000000FFFF0000u,
      0x000000000000FF00u,
      0x00000000000000F0u,
      0x000000000000000Cu,
      0x0000000000000002u
    };

    ::std::uint64_t y = (((x & (x - 1)) == 0) ? 0 : 1);
    ::std::uint64_t j = 32;

    for (const ::std::uint64_t& t_i : t) {
      ::std::uint64_t k = (((x & t_i) == 0) ? 0 : j);
      y += k;
      x >>= k;
      j >>= 1;
    }

    return y;
  }

  ::std::int32_t ceil_log2(::std::int32_t x) {
    return static_cast<::std::int32_t>(::tools::ceil_log2(static_cast<::std::uint32_t>(x)));
  }

  ::std::int64_t ceil_log2(::std::int64_t x) {
    return static_cast<::std::int64_t>(::tools::ceil_log2(static_cast<::std::uint64_t>(x)));
  }
}

// lib/segtree.hpp
#ifndef SEGTREE_HPP
#define SEGTREE_HPP


/*
usage:

// 6要素の区間和セグ木
tools::segtree<i64> segtree(
  tools::group<i64>::plus(),
  6,
  0
);

// 0始まりで3番目の要素に30を加算
segtree.update(3, segtree.query(3) + 30);
*/

namespace tools {
  template <typename T>
  class segtree {
  private:
    ::tools::monoid<T> monoid;
    ::std::size_t height;
    ::std::vector<T> data;

    void recalc(::std::size_t node_id) {
      while (node_id >>= 1) {
        this->data[node_id] = this->monoid.operation(this->data[(node_id << 1) | 0], this->data[(node_id << 1) | 1]);
      }
    }

    ::std::size_t capacity() const {
      return this->data.size() / 2;
    }

  public:
    segtree(
      const ::tools::monoid<T>& monoid,
      const ::std::size_t& n
    ) :
      monoid(monoid),
      height(::tools::ceil_log2(n)),
      data(::tools::pow2(this->height + 1), monoid.identity()) {
    }

    template <typename U>
    segtree(
      const ::tools::monoid<T>& monoid,
      const ::std::size_t& n,
      const U& t,
      const ::std::function<T(U)>& map
    ) :
      monoid(monoid),
      height(::tools::ceil_log2(n)),
      data(::tools::pow2(this->height + 1), monoid.identity()) {
      for (::std::size_t node_id = this->capacity(); node_id < this->capacity() + n; ++node_id) {
        this->data[node_id] = map(t);
      }
      for (::std::size_t node_id = this->capacity() - 1; node_id > 0; --node_id) {
        this->data[node_id] = monoid.operation(this->data[(node_id << 1) | 0], this->data[(node_id << 1) | 1]);
      }
    }

    template <typename InputIter>
    segtree(
      const ::tools::monoid<T>& monoid,
      const InputIter& begin,
      const InputIter& end,
      const ::std::function<T(typename InputIter::value_type)>& map
    ) :
      monoid(monoid),
      height(::tools::ceil_log2(::std::distance(begin, end))),
      data(::tools::pow2(this->height + 1), monoid.identity()) {
      ::std::size_t node_id = this->size();
      for (auto it = begin; it != end; ++it, ++node_id) {
        this->data[node_id] = map(*it);
      }
      for (node_id = this->capacity() - 1; node_id > 0; --node_id) {
        this->data[node_id] = monoid.operation(this->data[(node_id << 1) | 0], this->data[(node_id << 1) | 1]);
      }
    }

    void update(const ::std::size_t i, const T& x) {
      const ::std::size_t i_id = i + this->capacity();
      this->data[i_id] = x;
      this->recalc(i_id);
    }

    T query(const ::std::size_t i) const {
      const ::std::size_t i_id = i + this->capacity();
      return this->data[i_id];
    }

    T query(const ::std::size_t a, const ::std::size_t b) const {
      if (a >= b) return this->monoid.identity();

      const ::std::size_t a_id = a + this->capacity();
      const ::std::size_t b_id = b + this->capacity() - 1;

      T vl = this->monoid.identity();
      T vr = this->monoid.identity();
      for (::std::size_t l = a_id, r = b_id + 1; l < r; l >>= 1, r >>= 1) {
        if (l & 1) {
          vl = this->monoid.operation(vl, this->data[l]);
          ++l;
        }
        if (r & 1) {
          --r;
          vr = this->monoid.operation(this->data[r], vr);
        }
      }
      return this->monoid.operation(vl, vr);
    }
  };
}

#endif

// lib/group.hpp
#ifndef GROUP_HPP
#define GROUP_HPP


namespace tools {
  template <typename T>
  class group : public ::tools::monoid<T> {
  private:
    ::std::function<T(T)> m_inverse;

  public:
    group(const ::std::function<T(T, T)>& operation, const T& identity, const ::std::function<T(T)>& inverse) :
      ::tools::monoid<T>(operation, identity), m_inverse(inverse) {
    }
    group(const ::tools::group<T>&) = default;
    group(::tools::group<T>&&) = default;
    ::tools::group<T>& operator=(const ::tools::group<T>&) = default;
    ::tools::group<T>& operator=(::tools::group<T>&&) = default;
    virtual ~group() = default;

    T inverse(const T& x) const {
      return this->m_inverse(x);
    }

    template <typename U = T, typename ::std::enable_if<::std::is_integral<U>::value, ::std::nullptr_t>::type = nullptr>
    static ::tools::group<U> plus() {
      return ::tools::group<U>(::std::plus<U>(), 0, ::std::negate<U>());
    }
  };
}

#endif

// main.cpp

int main() {
  i64 N, Q;
  std::string S;
  std::cin >> N >> S >> Q;

  std::unordered_map<char, tools::segtree<i64>> segtree_map;
  for (const char& c : "abcdefghijklmnopqrstuvwxyz") {
    segtree_map.emplace(c, tools::segtree<i64>(tools::group<i64>::plus(), N));
  }
  for (i64 i = 0; i < N; ++i) {
    segtree_map.find(S[i])->second.update(i, 1);
  }

  for (i64 q = 0; q < Q; ++q) {
    i64 type;
    std::cin >> type;
    switch (type) {
    case 1:
      {
        i64 i_q;
        char c_q;
        std::cin >> i_q >> c_q;
        --i_q;

        segtree_map.find(S[i_q])->second.update(i_q, segtree_map.find(S[i_q])->second.query(i_q) - 1);
        segtree_map.find(c_q)->second.update(i_q, segtree_map.find(c_q)->second.query(i_q) + 1);
        S[i_q] = c_q;
      }
      break;

    case 2:
      {
        i64 l_q, r_q;
        std::cin >> l_q >> r_q;
        --l_q;

        i64 answer = 0;
        for (const char& c : "abcdefghijklmnopqrstuvwxyz") {
          if (segtree_map.find(c)->second.query(l_q, r_q) > 0) {
            ++answer;
          }
        }
        std::cout << answer << std::endl;
      }
      break;
    }
  }

  return 0;
}

Measured memory_bytes: 222212