CSES - Shared codeLink to this code: https://cses.fi/paste/db9c829451cae540ae1516/
/*
    AUTHOR -> KIMJONGOOF (CODEFORCES)
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define int long long
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
typedef tree<int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_multiset;
const int mod = 1e9 + 7;
const int inf = 1e18;
const int K = 26;
/*
 __builtin_popcountll(x): Counts the number of one’s(set bits) in an integer(long/long long).
 __builtin_parityll(x): Checks the Parity of a number.Returns true(1) if the number has odd parity(odd number of set bits) else it returns false(0) for even parity(even number of set bits).
 __builtin_clzll(x): Counts the leading number of zeros of the integer(long/long long).
 __builtin_ctzll(x): Counts the trailing number of zeros of the integer(long/long long).
cout << fixed << setprecision(x) << ans << "\n"; : Use this in case ans is required upto x deciaml precision
kuch nai sooj rha? binary search try kiya ??
*/

// Normal segment tree without lazy propagation..

struct node
{
    // node e ki ki thakbe bhabho bhalo kore!!
    int sum;
    node()
    {
        sum = 0;
    }
};

node merge(node a, node b)
{
    // nodes er merge korar logic ki?
    //  kokhono xor koro kokhono min-max to kokhono sum and so on..
    node ans;
    ans.sum = a.sum + b.sum;
    return ans;
}

vector<node> t;
vector<int> cnt;

void build(int id, int l, int r)
{
    if (l == r)
    {
        // Eita kintu leaf node
        // initializing logic set korte hobe eikhane
        t[id].sum = cnt[l];
        return;
    }
    // tarpor to shudu O(logn) e shob update hobe..
    int mid = (l + r) >> 1;
    build(2 * id, l, mid);
    build(2 * id + 1, mid + 1, r);
    t[id] = merge(t[2 * id], t[2 * id + 1]);
}

void update(int id, int l, int r, int pos, int val)
{
    if (pos < l || pos > r)
    {
        // eikhane kono overlap hobe na
        // kichu korte hobe na
        return;
    }

    if (l == r)
    {
        // mane amra pos index e pohuche gachi eibaar shudu update koro ar tarpor return!!
        t[id].sum += val;
        return;
    }

    // tarpor to as usual (Ologn) e update koro..
    int mid = (l + r) >> 1;
    update(2 * id, l, mid, pos, val);
    update(2 * id + 1, mid + 1, r, pos, val);
    t[id] = merge(t[2 * id], t[2 * id + 1]);
}

node query(int id, int l, int r, int lo, int hi)
{
    if (lo > r || l > hi)
    {
        // thik ager moton eikhane o kono overlap nei, to kichu korte hobe na
        return node(); // eita kintu shob shomaye thik na, just sum er case e thik
        // ei case e ki return hobe sheita bhabte hobe..
    }

    if (lo <= l && hi >= r)
    {
        // again ager moton eikhane puro overlao hoche, so just return the entire node
        return t[id];
    }

    int mid = (l + r) >> 1;
    return merge(query(2 * id, l, mid, lo, hi), query(2 * id + 1, mid + 1, r, lo, hi));
}

int n, q;
vector<int> a, stor;
vector<vector<int>> queries;
int get_val(vector<int> &a, int val)
{
    int ind = lower_bound(a.begin(), a.end(), val) - a.begin();
    return ind;
}
void solve()
{
    cin >> n >> q;
    a.assign(n, 0);
    stor.clear();
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
        stor.push_back(a[i]);
    }

    while (q--)
    {
        char tt;
        int aa, b;
        cin >> tt >> aa >> b;
        queries.push_back({tt == '!', aa, b});
        stor.push_back(aa);
        stor.push_back(b);
    }

    sort(stor.begin(), stor.end());
    stor.erase(unique(stor.begin(), stor.end()), stor.end());

    int sz = stor.size();
    cnt.assign(sz, 0);
    for (auto it : a)
    {
        cnt[get_val(stor, it)]++;
    }

    t.assign(4 * sz, node());
    build(1, 0, sz - 1);

    for (auto it : queries)
    {
        if (it[0] == 1)
        {
            int nval = get_val(stor, a[it[1] - 1]);
            update(1, 0, sz - 1, nval, -1);
            a[it[1] - 1] = it[2];
            update(1, 0, sz - 1, get_val(stor, it[2]), 1);
        }
        else
        {
            cout << query(1, 0, sz - 1, get_val(stor, it[1]), get_val(stor, it[2])).sum << "\n";
        }
    }

    return;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int _ = 1;
    // cin >> _;
    for (int __ = 1; __ <= _; __++)
    {
        solve();
    }
}