map implementation of Kodori tree

Posted by Sudden on Sun, 20 Feb 2022 15:08:29 +0100

1 Introduction

Recently, I looked at jiangly's CF1638E code and found that jiangly's Kodori tree is implemented with map. So I studied it.

CF1638E jiangly code

If you haven't come into contact with the Kodori tree, please learn the following first.

The principle and set implementation of Kodori tree

Complexity analysis of Kodori tree

CF1638E solution to the problem of cordoli tree

2. map implementation principle of cordolly tree

In the set implementation of the Kodori tree, an interval is recorded as [ l , r , v a l ] [l, r, val] [l,r,val], respectively represents the left end point of the interval, the right end point of the interval, and the value stored in the interval.

However, since the interval of the Kodori tree is adjacent to the interval, the right endpoint of this interval must be the left endpoint of the next interval, so we can simply record an interval as [ l , v a l ] [l, val] [l,val], respectively representing the left end point of the interval and the value stored in the interval.

In this way, we can directly use the standard library map. For an interval, we will l l l is recorded as the kep value in the map v a l val val is recorded as the value in the map. This makes it easier to write and less code.

3. map implementation method of Kodori tree

First, go directly to the complete code.

struct ODT {
    const int n;
    map<int, int> mp;
    ODT(int n) : n(n) { mp[-1] = 0 }
    void split(int x) {
        auto it = prev(mp.upper_bound(x)); //Find the interval where the left endpoint is less than or equal to x
        mp[x] = it->second; //Set up a new interval and copy the value stored in the previous interval to this interval.
    }
    void assign(int l, int r, int v) { // Note that r here is the right endpoint of the interval + 1
        split(l);
        split(r);
        auto it = mp.find(l);
        while (it->first != r) {
            it = mp.erase(it);
        }
        mp[l] = v;
    }
    void update(int l, int r, int c) { // Other operations
        split(l);
        split(r);
        auto it = mp.find(l);
        while (it->first != r) {
            // What needs to be done according to the topic
            it = next(it);
        }
    }
};

Then we explain them one by one

3.1 initialization

Let the interval subscript be [ 0 , n āˆ’ 1 ] [0, n - 1] [0,nāˆ’1].
Since there is only one interval at the beginning, that is [ 0 , n āˆ’ 1 ] [0, n - 1] [0,n − 1], then when we initialize, we only insert a left endpoint as 0 0 Interval of 0.

	ODT(int n) : n(n) { mp[-1] = 0 }

3.2 split operation

Suppose we need to x x x establishes a new interval for the left endpoint. We directly find the left endpoint less than or equal to in the map x x Set up a new interval and copy the value stored in the previous interval to this interval.

	void split(int x) {
        auto it = prev(mp.upper_bound(x)); //Find the interval where the left endpoint is less than or equal to x
        mp[x] = it->second; //Set up a new interval and copy the value stored in the previous interval to this interval.
    }

3.3 assign operation

For the assign operation, we need to [ l , r āˆ’ 1 ] [l, r-1] Delete the left end point of all intervals in [l,r − 1], and then create a new interval.

    void assign(int l, int r, int v) { // Note that r here is the right endpoint of the interval + 1
        split(l);
        split(r);
        auto it = mp.find(l);
        while (it->first != r) {
            it = mp.erase(it);
        }
        mp[l] = v;
    }
};

3.4 other operations

	void update(int l, int r, int c) { // Other operations
        split(l);
        split(r);
        auto it = mp.find(l);
        while (it->first != r) {
            // What needs to be done according to the topic
            it = next(it);
        }
    }

4 CF1638E implementation code of cordoli tree

#include <bits/stdc++.h>
using namespace std;

using i64 = long long;
using ldb = long double;
#define int i64
#define double ldb

template <typename T>
struct BIT {
    const int n;
    std::vector<T> a;
    BIT(int n) : n(n), a(n) {}
    void add(int x, T v) {
        for (int i = x + 1; i <= n; i += i & -i) {
            a[i - 1] += v;
        }
    }
    void rangeAdd(int l, int r, T v) {
        add(l, v);
        add(r, -v);
    }
    T sum(int x) {
        T ans = 0;
        for (int i = x + 1; i > 0; i -= i & -i) {
            ans += a[i - 1];
        }
        return ans;
    }
    T rangeSum(int l, int r) {
        return sum(r) - sum(l);
    }
};

struct ODT {
    const int n;
    map<int, int> mp;
    vector<int> lazy;
    BIT<int> bit;
    ODT(int n) : n(n), lazy(n), bit(n) { mp[-1] = 0; }
    void split(int x) {
        auto it = prev(mp.upper_bound(x));
        mp[x] = it->second;
    }
    void assign(int l, int r, int v) {
        split(l);
        split(r);
        auto it = mp.find(l);
        while (it->first != r) {
            it = mp.erase(it);
        }
        mp[l] = v;
    }
    void update(int l, int r, int c) {
        split(l);
        split(r);
        auto it = mp.find(l);
        while (it->first != r) {
            bit.rangeAdd(it->first, next(it)->first, lazy[it->second] - lazy[c]);
            it = next(it);
        }
    }
    void add(int c, int x) {
        lazy[c] += x;
    }
    int query(int x) {
        split(x);
        return bit.sum(x) + lazy[mp[x]];
    }
};

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, q;
    cin >> n >> q;

    ODT odt(n);

    for (int i = 0; i < q; i++) {
        string op;
        cin >> op;
        if (op == "Color") {
            int l, r, c;
            cin >> l >> r >> c;
            l--;
            c--;

            odt.update(l, r, c);
            odt.assign(l, r, c);
        }
        else if (op == "Add") {
            int c, x;
            cin >> c >> x;
            c--;

            odt.add(c, x);
        }
        else if (op == "Query") {
            int x;
            cin >> x;
            x--;

            cout << odt.query(x) << "\n";
        }
    }
    return 0;
}

Topics: Algorithm data structure