/**
 * Contest : 
 * Contest URL : 
 * Problem : 
 * Problem URL : 
 */

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair < int, int >;

// This section is for Policy Based Data Structure, more precisely Ordered Set.
// All Functions of set works here, in addition we have order_of_key() and find_by_order() function. find_by_order() returns iterator
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<functional>
using namespace __gnu_pbds;

// 1. Custom Set
template < class T, class COMP >
using custom_set = tree < T, null_type, COMP, rb_tree_tag, tree_order_statistics_node_update >;

// 2. Ordered Set
template < class T >
using ordered_set = tree < T, null_type, less < T >, rb_tree_tag, tree_order_statistics_node_update >;

// 3. Ordered Multi Set
// For storing multiple occurance of same value we need to use pair. In pair first value is our key and second is useless count variable.
// order_of_key(make_pair(key, 0)) returns first occurance of a value, order_of_key(make_pair(key, INT_MAX)) returns last occurance.
template < class T >
using ordered_multiset = tree < pair < T, int >, null_type, less < pair < T, int > >, rb_tree_tag, tree_order_statistics_node_update >;

// 4. Ordered Map
template < class T, class U >
using ordered_map = tree < T, U, less < T >, rb_tree_tag, tree_order_statistics_node_update >;
// Policy End

struct SegmentTreeNode {
	int count[26];
	
	void assignLeafValue (char c) {
		for (int i = 0; i < 26; i++) {
			count[i] = 0;
		}
		count[c - 'a']++;
	}
	
	void merge (SegmentTreeNode & left, SegmentTreeNode & right) {
		for (int i = 0; i < 26; i++) {
			count[i] = left.count[i] + right.count[i];
		}
	}
	
	int getValue () {
		int cnt = 0;
		for (int i = 0; i < 26; i++) {
			cnt += (count[i] > 0);
		}
		return cnt;
	}
};

template < class T, class V >
class SegmentTree {
	vector < SegmentTreeNode > tree;
	int N;
	
	private:
	int getSegmentTreeSize (int n) {
		int sz = 1;
		for (;sz < N; sz <<= 1);
		return sz << 1;
	}
	
	void buildTree (vector < T > & arr, int low, int high, int pos) {
		if (low == high) {
			tree[pos].assignLeafValue (arr[low]);
			return;
		}
		int mid = low + (high - low) / 2;
		buildTree (arr, low, mid, 1 + (pos << 1));
		buildTree (arr, mid + 1, high, 2 + (pos << 1));
		tree[pos].merge (tree[1 + (pos << 1)], tree[2 + (pos << 1)]);
	}
	
	void update (int index, T value, int low, int high, int pos) {
		if (index < low || index > high) return;
		if (low == high) {
			tree[pos].assignLeafValue (value);
			return;
		}
		int mid = low + (high - low) / 2;
		update (index, value, low, mid, 1 + (pos << 1));
		update (index, value, mid + 1, high, 2 + (pos << 1));
		tree[pos].merge (tree[1 + (pos << 1)], tree[2 + (pos << 1)]);
	}
	
	SegmentTreeNode query (int left, int right, int low, int high, int pos) {
		if (left <= low && right >= high) {
			return tree[pos];
		}
		
		//if (left > right) {
			//return 
		
		int mid = (low + high) / 2;
		if (left > mid) {
			return query (left, right, mid + 1, high, 2 + (pos << 1));
		} else if (right <= mid) {
			return query (left, right, low, mid, 1 + (pos << 1));
		}
		
		SegmentTreeNode leftResult = query (left, right, low, mid, 1 + (pos << 1));
		SegmentTreeNode rightResult = query (left, right, mid + 1, high, 2 + (pos << 1));
		SegmentTreeNode result;
		result.merge (leftResult, rightResult);
		return result;
	}
	
	public:
	SegmentTree (vector < T > & arr) {
		N = arr.size();
		tree.resize (getSegmentTreeSize(N));
		buildTree (arr, 0, N - 1, 0);
	}
	
	~SegmentTree () {
		tree.resize (0);
	}
	
	V query (int left, int right) {
		SegmentTreeNode result = query (left, right, 0, N - 1, 0);
		return result.getValue();
	}
	
	void update (int index, T value) {
		update (index, value, 0, N - 1, 0);
	}
};

int main() {
	ios_base::sync_with_stdio (false);
	cin.tie (0); cout.tie (0);
	
	int n, q, type, l, r;
	string s;
	char c;
	
	cin >> n >> s >> q;
	assert (n == s.size());
	vector < char > a;
	for (char c : s) a.push_back (c);
	SegmentTree < char, int > st (a);
	while (q--) {
		cin >> type;
		if (type == 1) {
			cin >> l >> c;
			st.update (l - 1, c);
		} else {
			cin >> l >> r;
			int answer = st.query (l - 1, r - 1);
			cout << answer << "\n";
		}
	}
	
	return 0;
}



Measured memory_bytes: 108316