区间修改

小红的区间修改(二)

区间差分与合并,珂朵树

版本一

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

struct query{
    int left, right;
    ll c;
    bool operator <(const query& other) const {
        return left < other.left;
    }
};

void solve() {
    int q; cin >> q;

    map<ll, int> col;
    set<query> val;
    int INF = 1e6;
    val.insert({1, INF, 0}); col[0] = 1e6;
    int ans = 1;

    while(q --) {
        int l, r, x; cin >> l >> r >> x;
        auto it = val.lower_bound({l, r, x});
        if(it == val.end() || (it!=val.begin() && prev(it)->left <= l && prev(it)->right >= r)) {
            it = prev(it);
            if(it->c != x) {
                int L = it->left, R = it->right;
                ll C = it->c;
                val.erase(it);

                col[it->c] -= r - l + 1;
                if(col[x] == 0) ans ++;
                col[x] += r - l + 1;

                if(L <= l-1) val.insert({L, l-1, C});
                if(r + 1 <= R) val.insert({r+1, R, C});
                
                val.insert({l, r, x}); 
                
            }
            cout << ans << "\n";
            continue;
        }

        if(it->left > l) {
            auto pit = prev(it);
            int PL = pit->left, PR = pit->right;
            ll PC = pit->c;
            val.erase(pit);

            if(PC == x) {
                l = PL;
                col[x] -= PR - PL + 1;
                if(col[x] == 0) ans --;
            } else {
                col[PC] -= PR - l + 1;
                if(PL <= l - 1) val.insert({PL, l - 1, PC});
            }
        }
        while(it != val.end() && it->right <= r) {
            auto w = it;
            it = next(it);
            col[w->c] -= w->right - w->left + 1;
            if(col[w->c] == 0) ans --;
            val.erase(w);
        }
        if(it->left <= r)  {
            if(it->c == x) {
                r = it->right;
                col[x] -= it->right - it->left + 1;
                if(col[x] == 0) ans --;
                val.erase(it);
            } else {
                int L = it->left, R = it->right;
                ll C = it->c;
                col[C] -= r - L + 1;
                val.erase(it);
                if (r + 1 <= R) val.insert({r + 1, R, C});
            }
        }

        if(col[x] == 0) ans ++;
        col[x] += r - l + 1;
        val.insert({l, r, x});

        cout << ans << "\n";
    }
}

int main() {
    ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
    solve();
    return 0;
}

版本二

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

struct query{
    int left, right;
    ll c;
    bool operator <(const query& other) const {
        if(left != other.left) return left < other.left;
        else if(right != other.right) return right < other.right;
        return c < other.c;
    }
};

void solve() {
    int q; cin >> q;

    map<ll, int> col;
    set<query> val;
    int INF = 1e6;
    val.insert({1, INF, 0}); col[0] = 1e6;
    int ans = 1;

    while(q --) {
        int l, r, x; cin >> l >> r >> x;
        auto it = val.lower_bound({l, r, x});
        if(it == val.end() || (it!=val.begin() && prev(it)->left <= l && prev(it)->right >= r)) {
            it = prev(it);
            if(it->c != x) {
                col[it->c] -= r - l + 1;
                if(col[it->c] == 0) ans --;
                if(col[x] == 0) ans ++;
                col[x] += r - l + 1;

                if(it->left <= l-1) {query pr = {it->left, l - 1, it->c}; val.insert(pr);}
                if(r + 1 <= it->right) {query su = {r + 1, it->right, it->c};val.insert(su);}
                
                val.insert({l, r, x}); 
                val.erase(it);
            }
            cout << ans << "\n";
            continue;
        }

        if(it->left > l) {
            auto pit = prev(it);
            if(pit->c == x) {
                l = pit->left;
                col[x] -= pit->right - pit->left + 1;
            } else {
                col[pit->c] -= pit->right - l + 1;
                if(pit->left < l) val.insert({pit->left, l - 1, pit->c});
            }
            if(col[pit->c] == 0) ans --;
            val.erase(pit);
        }
        while(true) {
            if(it->right > r) break;
            auto w = it; it = next(it);
            col[w->c] -= w->right - w->left + 1;
            if(col[w->c] == 0) ans --;
            val.erase(w);
        }
        if(it->left <= r)  {
            if(it->c == x) {
                r = it->right;
                col[x] -= it->right - it->left + 1;
            } else {
                col[it->c] -= r - it->left + 1;
                if(r < it->right) val.insert({r + 1, it->right, it->c});
            }
            if(col[it->c] == 0) ans --;
            val.erase(it);
        }

        if(col[x] == 0) ans ++;
        col[x] += r - l + 1;
        val.insert({l, r, x});

        cout << ans << "\n";
    }
}

int main() {
    ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
    solve();
    return 0;
}

版本三——珂朵树

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int INF = 1e9;

struct Node {
    int l, r;
    mutable ll val;// mutable 允许在 set 中修改 val
    Node(int _l, int _r = -1, ll _val = 0) : l(_l), r(_r), val(_val) {}
    bool operator<(const Node& o) const {
        return l < o.l;
    }
};

set<Node> tree;
map<ll, int> cnt; 
int ans = 1;

// 将 pos 所在段分裂成 [l, pos-1] 和 [pos, r],返回 pos 所在段的迭代器
auto split(int pos) {
    auto it = tree.lower_bound(Node(pos));
    if(it != tree.end() && it->l == pos) return it;
    --it;                               // it 现在是包含 pos 的段
    int L = it->l, R = it->r;
    ll V = it->val;
    tree.erase(it);
    if(L <= pos - 1) tree.insert(Node(L, pos - 1, V));
    return tree.insert(Node(pos, R, V)).first;
}

// 区间 [l, r] 赋值为 val
void assign(int l, int r, ll val) {
    auto itr = split(r + 1);            // 先切右端点,防止迭代器失效
    auto itl = split(l);                // 再切左端点
    // 删除 [itl, itr) 的所有段,并更新 cnt
    for(auto it = itl; it != itr; ++it) {
        int len = it->r - it->l + 1;
        cnt[it->val] -= len;
        if(cnt[it->val] == 0) ans--;
    }
    tree.erase(itl, itr);
    tree.insert(Node(l, r, val));
    cnt[val] += r - l + 1;
    if(cnt[val] == r - l + 1) ans ++;// 等价于原来 cnt[val]==0
}

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

    int q; cin >> q;
    tree.insert(Node(1, INF, 0));
    cnt[0] = INF;

    while(q --) {
        int l, r, x; cin >> l >> r >> x;
        assign(l, r, x);
        cout << ans << '\n';
    }
    return 0;
}
posted @ 2026-10-03 09:53  thenrify  阅读(5)  评论(0)    收藏  举报