Topics

Problem is straightforward. You are given a string of size N and Q queries. Queries of Type 1 ask you replace a character with the provided character c, while Type 2 queires ask you to print the number of distinct characters in the given range [l, r].

Idea

This can be solved using advanced data structures such as segment trees, but something like a C++ set (i.e balanced binary search trees) can be smartly used to solve this.

For each alphabet (26 total), we can store the indices where they occur in the string in a set. Type 1 queries can be processed in O(log N) using the erase and insert functions. For Type 2 queries, all we want to do is check for each alphabet if any of it’s occurrences fall within the range or not. To do this, we can find the first occurrence of the character after the l-th position using the lower_bound function for each character and comparing that value with r. This will also take O(log N) time.

Time Complexity:
Space Complexity:

Code

void solve() {
  int n;
  cin >> n;
  string s;
  cin >> s;
 
  vector<set<int>> occ(26);
  for (int i = 0; i < n; ++i) {
    occ[s[i] - 'a'].insert(i);
  }
 
  int q, t;
  cin >> q;
 
  while (q--) {
    cin >> t;
    if (t == 2) {
      // query
      int l, r;
      cin >> l >> r;
      l--, r--; // 0-based idx
      int count = 0;
      for (int i = 0; i < 26; ++i) {
        auto it = occ[i].lower_bound(l);
        if (it != occ[i].end() and *it <= r)
          count++;
      }
      cout << count << '\n';
 
    } else {
      // update
      int idx;
      char c;
      cin >> idx >> c;
 
      idx -= 1; // 0-based idx
      int curr = s[idx] - 'a';
      occ[curr].erase(idx);
      occ[c - 'a'].insert(idx);
      s[idx] = c;
    }
  }
}