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);
}
}
}