• + 0 comments

    time and space using a segment tree of ordered_set.

    #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;
    
    template<typename T>
    using ordered_set = tree<
        T, null_type, less<T>, rb_tree_tag,
        tree_order_statistics_node_update>;
    
    vector<int> s;
    vector<ordered_set<pair<int, int>>> seg;
    
    // O(n*log(n)*log(n))
    void segbuild(int x, int lx, int rx) {
        if (rx - lx == 1) {
            seg[x].insert({s[lx], lx});
            return;
        }
        int mid = (lx + rx) / 2;
        segbuild(x * 2 + 1, lx, mid);
        segbuild(x * 2 + 2, mid, rx);
        for (const auto& p : seg[x * 2 + 1]) seg[x].insert(p);
        for (const auto& p : seg[x * 2 + 2]) seg[x].insert(p);
    }
    
    // O(log(n)*log(n))
    void segset(int i, int k, int x, int lx, int rx) {
        seg[x].erase({s[i], i});
        seg[x].insert({k, i});
        if (rx - lx == 1) return;
        int mid = (lx + rx) / 2;
        if (i < mid) segset(i, k, x * 2 + 1, lx, mid);
        else segset(i, k, x * 2 + 2, mid, rx);
    }
    
    // O(log(n))
    void segrange(
        int l, int r, int x, int lx, int rx,
        vector<int>& v)
    {
        if (lx >= r || rx <= l) return;
        if (lx >= l && rx <= r) {
            v.push_back(x);
            return;
        }
        int mid = (lx + rx) / 2;
        segrange(l, r, x * 2 + 1, lx, mid, v);
        segrange(l, r, x * 2 + 2, mid, rx, v);
    }
    
    int main() {
        int t; cin >> t;
        for (; t > 0; --t) {
            int n; cin >> n;
            s.assign(n, 0);
            for (int& x : s) cin >> x;
            seg.assign(n * 4, ordered_set<pair<int, int>>());
            segbuild(0, 0, n);
            int q; cin >> q;
            for (; q > 0; --q) {
                int type; cin >> type;
                if (type == 1) {
                    // O(log(n)*log(n))
                    int x, k; cin >> x >> k;
                    segset(x - 1, k, 0, 0, n);
                    s[x - 1] = k;
                } else {
                    // O(log(k)*log(n)*log(n))
                    int x, y, k; cin >> x >> y >> k;
                    vector<int> v;
                    segrange(x - 1, y, 0, 0, n, v);
                    int lo = 0;
                    int hi = 1000;
                    while (hi - lo > 1) {
                        int mid = (lo + hi) / 2;
                        int cnt = 0;
                        for (int x : v)
                            cnt += seg[x].order_of_key({mid + 1, 0});
                        if (cnt < k) lo = mid;
                        else hi = mid;
                    }
                    cout << hi << "\n";
                }
            }
        }
    }