Range Sets(The 2nd Universal Cup. Stage 7: Two Capital)

Range Sets(The 2nd Universal Cup. Stage 7: Two Capital)

题目 J: Range Sets(数据结构)

题目链接

题目分析:

(动态开点线段树)

这是一道数据结构题目,涉及动态开点线段树的操作。通过使用线段树,我们可以高效处理区间修改和单点查询操作。这种数据结构可以用于优化时间复杂度,在面对较大的数据范围时尤为实用。后续会更新更详细的讲解。

代码实现:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define BoBoowen ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)

const int N = 1e5 + 10;
int tot, rt;
int n, q;

struct SMT
{
    int ls, rs;
    int v;
} seg[N * 40];

struct Node
{
    int l, r;
    mutable int val;
    Node(int _l, int _r, int _val) : l(_l), r(_r), val(_val) {}
    bool operator<(const Node &other) const
    {
        return l < other.l;
    }
};

typedef set<Node>::iterator S_IT;

inline void modify(int &id, int l, int r, int ql, int qr, int v)
{
    if (!id)
    {
        id = ++tot;
    }
    if (ql <= l && r <= qr)
    {
        seg[id].v += v;
        return;
    }
    int mid = (l + r) >> 1;
    if (ql <= mid)
    {
        modify(seg[id].ls, l, mid, ql, qr, v);
    }
    if (qr > mid)
    {
        modify(seg[id].rs, mid + 1, r, ql, qr, v);
    }
}

inline int query(int id, int l, int r, int pos)
{
    if (!id)
    {
        return 0;
    }
    int mid = (l + r) >> 1;
    if (pos <= mid)
    {
        return query(seg[id].ls, l, mid, pos) + seg[id].v;
    }
    else
    {
        return query(seg[id].rs, mid + 1, r, pos) + seg[id].v;
    }
}

struct ODT
{
    set<Node> s;
    S_IT split(int pos)
    {
        auto it = s.lower_bound(Node(pos, 0, 0));
        if (it != s.end() && it->l == pos)
        {
            return it;
        }
        if (it == s.begin())
        {
            return s.end();
        }
        --it;
        int l = it->l, r = it->r;
        int v = it->val;
        s.erase(it);
        s.insert(Node(l, pos - 1, v));
        return s.insert(Node(pos, r, v)).first;
    }
    inline void assign(int L, int R, int v)
    {
        S_IT itr = split(R + 1), itl = split(L);
        for (S_IT it = itl; it != s.end() && it->l <= R;)
        {
            if (it->val != v)
            {
                modify(rt, 1, n, it->l, it->r, v - it->val);
            }
            it = s.erase(it);
        }
        s.insert(Node(L, R, v));
    }
} tr[N * 40];

signed main()
{
    BoBoowen;

    cin >> n >> q;
    unordered_map<int, int> mp;
    while (q--)
    {
        char op;
        cin >> op;
        if (op == '?')
        {
            int pos;
            cin >> pos;
            cout << query(rt, 1, n, pos) << endl;
        }
        else if (op == '-')
        {
            int l, r, x;
            cin >> l >> r >> x;
            if (!mp.count(x))
            {
                mp[x] = ++tot;
                tr[mp[x]].s.insert(Node(1, n, 0));
            }
            tr[mp[x]].assign(l, r, 0);
        }
        else
        {
            int l, r, x;
            cin >> l >> r >> x;
            if (!mp.count(x))
            {
                mp[x] = ++tot;
                tr[mp[x]].s.insert(Node(1, n, 0));
            }
            tr[mp[x]].assign(l, r, 1);
        }
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值