CF1034D Intervals of Intervals

Posted kyEEcccccc@cnblogs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1034D Intervals of Intervals相关的知识,希望对你有一定的参考价值。

简要题意

给定 \\(n\\) 个区间组成的序列,定义它的一个连续段的价值为这个段内所有区间的并覆盖的长度。求价值前 \\(k\\) 大的段的价值和。

数据范围:\\(1\\le n\\le 3\\times 10^5, 1\\le k\\le \\min\\\\fracn(n-1)2, 10^9\\\\)

题解

考虑一个经典问题,\\(q\\) 次询问求某个连续段的价值。考虑离线,动态维护对于当前右端点,每个左端点的答案。考虑一个位置最后一次被覆盖是在第 \\(t\\) 个区间,那么对于所有 \\(1\\le l\\le t\\) 这个位置都会贡献 \\(1\\)。那么考虑将右端点右移一位时如何维护。显然类似珂朵莉树,可以证明修改段的次数是均摊 \\(\\mathrm O(n)\\)。那么直接考虑用线段树,修改段等价于一次区间加。总时间复杂度 \\(\\mathrm O(n\\log n)\\)。把线段树换成主席树,可以做到在线询问。

接着考虑这题,容易想到先找到排名为 \\(k\\) 的连续段的价值,就很好做了,那么二分答案,转化为计数价值大于 \\(X\\) 的连续段。考虑一个结论:\\(V(L_i, R_i + 1)\\ge V(L_i, R_i) \\ge V(L_i + 1, R_i)\\)。则存在 \\(pos(r, X)\\) 为最大的 \\(l\\) 使得 \\(V(l, r) > X\\)。同时容易得出,\\(V(r, X)\\) 关于 \\(r\\) 单增。通过一个指针维护,把珂朵莉树放在二分外面,预处理出每个 \\(r\\) 增加的区间,用前缀和维护即可,时间复杂度 \\(\\mathrm O(n\\log n)\\)

data-stream-as-disjoint-intervals

https://leetcode.com/problems/data-stream-as-disjoint-intervals/

/**
 * Definition for an interval.
 * struct Interval {
 *     int start;
 *     int end;
 *     Interval() : start(0), end(0) {}
 *     Interval(int s, int e) : start(s), end(e) {}
 * };
 */
class SummaryRanges {
    vector<Interval> vec;
    int find(int val) {
        int vlen = vec.size();
        if (vlen == 0) {
            return -1;
        }
        int begin = 0;
        int end = vlen - 1;
        int mid;
        while (begin <= end) {
            mid = begin + (end - begin) / 2;
            // Here <= vs. >
            if (vec[mid].start > val) {
                end = mid - 1;
            }
            else {
                begin = mid + 1;
            }
        }
        // Here it‘s important to return end
        return end;
    }
    
public:
    /** Initialize your data structure here. */
    SummaryRanges() {
        
    }
    
    void addNum(int val) {
        int idx = find(val);
        if (idx < 0) {
            if (vec.size() > 0 && vec[0].start == val+1) {
                vec[0].start = val;
            }
            else {
                Interval inter(val, val);
                vec.insert(vec.begin(), inter);
            }
        }
        else {
            if (vec[idx].end == val-1) {
                vec[idx].end = val;
            }
            else if (vec[idx].end < val-1) {
                Interval inter(val, val);
                vec.insert(vec.begin()+idx+1, inter);
                idx++;
            }
            // check latter
            if (vec.size() > idx+1 && vec[idx+1].start == vec[idx].end + 1) {
                vec[idx].end = vec[idx+1].end;
                vec.erase(vec.begin()+idx+1);
            }
        }
    }
    
    vector<Interval> getIntervals() {
        return vec;
    }
};

/**
 * Your SummaryRanges object will be instantiated and called as such:
 * SummaryRanges obj = new SummaryRanges();
 * obj.addNum(val);
 * vector<Interval> param_2 = obj.getIntervals();
 */

 

以上是关于CF1034D Intervals of Intervals的主要内容,如果未能解决你的问题,请参考以下文章

56. Merge Intervals

Merge Intervals

data-stream-as-disjoint-intervals

LeetCodeMerge Intervals 题解 利用Comparator进行排序

CF游戏出现out of memory 怎么解决

DAX-DATEADD疑惑