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&动态开点)的主要内容,如果未能解决你的问题,请参考以下文章

zzuli-2276跳一跳

hdu2276---Kiki &amp; Little Kiki 2(矩阵)

[HDU2276]Kiki & Little Kiki 2

HDU2276——Kiki & Little Kiki 2

HDU 2276 Kiki & Little Kiki 2

hdu 2276 Kiki & Little Kiki 2 矩阵快速幂