2276. 统计区间中的整数数目(set&动态开点)
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2276. 统计区间中的整数数目(set&动态开点)相关的知识,希望对你有一定的参考价值。
2276. 统计区间中的整数数目(set&动态开点)
1.set合并
排序按照右端点从小到大,右端点相同左端点从小到大排序。
然后用一个cnt遍历维护答案。
每个区间最多被插入删除一次。
所以时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
class CountIntervals
typedef pair<int, int> pii;
int ans = 0;
set<pii> st;
public:
CountIntervals()
void add(int left, int right)
int L = left, R = right;
// 这里 (R1, L1) >= (R2, L2),若 R1 > R2 或 R1 = R2 且 L1 >= L2
auto it = st.lower_bound(pii(left - 1, -2e9));
while (it != st.end())
if (it->second > right + 1) break;
L = min(L, it->second);
R = max(R, it->first);
ans -= it->first - it->second + 1;
st.erase(it++);
ans += R - L + 1;
st.insert(pii(R, L));
int count()
return ans;
;
2.动态开点线段树
每个结点存对应的端点范围和对应的覆盖的个数。
class CountIntervals
CountIntervals *left = nullptr, *right = nullptr;
int l, r, cnt = 0;
public:
CountIntervals() : l(1), r(1e9)
CountIntervals(int l, int r) : l(l), r(r)
void add(int L, int R) // 为方便区分变量名,将递归中始终不变的入参改为大写(视作常量)
if (cnt == r - l + 1) return; // 当前节点已被完整覆盖,无需执行任何操作
if (L <= l && r <= R) // 当前节点已被区间 [L,R] 完整覆盖,不再继续递归
cnt = r - l + 1;
return;
int mid = (l + r) / 2;
if (left == nullptr) left = new CountIntervals(l, mid); // 动态开点
if (right == nullptr) right = new CountIntervals(mid + 1, r); // 动态开点
if (L <= mid) left->add(L, R);
if (mid < R) right->add(L, R);
cnt = left->cnt + right->cnt;
int count() return cnt;
;
以上是关于2276. 统计区间中的整数数目(set&动态开点)的主要内容,如果未能解决你的问题,请参考以下文章