[CCO 2020] Interval Collection
不显然的结论:最多选 \(2\) 个区间。因为多余 \(2\) 个的会导致浪费。
最大公共子区间 未定义
设线段树当前区间为 \(\left [ l, r \right ]\)。
用这个树存下面三个值。
- 
\(lt\) 表示左端点在当前区间时最小的右端点; 
- 
\(rt\) 表示右端点在当前区间时最大的左端点; 
- 
\(ans\) 表示当前区间中最小公共超区间的长度。 
线段树的左右子节点为 \(ls, rs\)。
用 \(rt_{rs}-lt_{ls}\) 更新当前节点的 \(ans\) 就行。
否则
令最大的左端点为 \(L\),最小的右端点为 \(R\)。
答案就是 \(L\) 对应的最小右端点与 \(R\) 对应的最大左端点的差。
#include <bits/stdc++.h>
#define ls p << 1
#define rs p << 1 | 1
#define mid (l + r >> 1)
using namespace std;
inline int read()
{
    int f = 0, ans = 0;
    char c = getchar();
    while (!isdigit(c))
        f |= c == '-', c = getchar();
    while (isdigit(c))
        ans = (ans << 3) + (ans << 1) + c - 48, c = getchar();
    return f ? -ans : ans;
}
void write(int x)
{
    if (x < 0)
        putchar('-'), x = -x;
    if (x > 9)
        write(x / 10);
    putchar(x % 10 + '0');
}
constexpr int N = 1e6 + 5, M = N << 2, inf = 1e9;
int m;
multiset<int> L, R, lt[N], rt[N];
struct Tree
{
    struct tree
    {
        int l, r, ans;
        tree() : l(-inf), r(inf), ans(inf) {}
        tree(int L, int R, int Ans) : l(L), r(R), ans(Ans) {}
    } tr[M];
    void update(int p)
    {
        tr[p] = {max(tr[ls].l, tr[rs].l), min(tr[ls].r, tr[rs].r),
                 min(min(tr[ls].ans, tr[rs].ans), tr[rs].r - tr[ls].l)};
    }
    void reupdate(int l, int r, int x, int p)
    {
        if (l == r)
        {
            tr[p].l = empty(lt[x]) ? -inf : *rbegin(lt[x]);
            tr[p].r = empty(rt[x]) ? inf : *begin(rt[x]);
            tr[p].ans = tr[p].r - tr[p].l;
            return;
        }
        if (mid >= x)
            reupdate(l, mid, x, ls);
        else
            reupdate(mid + 1, r, x, rs);
        update(p);
    }
    void reupdate(int x) { reupdate(1, 1e6, x, 1); }
    int get() { return tr[1].ans; }
} tr;
signed main()
{
    // freopen(".in", "r", stdin);
    // freopen(".out", "w", stdout);
    ios::sync_with_stdio(NULL);
    cin.tie(nullptr), cout.tie(nullptr);
    cin >> m;
    while (m--)
    {
        char op;
        int l, r;
        cin >> op >> l >> r;
        if (op == 'A')
        {
            L.insert(l), R.insert(r);
            lt[r].insert(l), rt[l].insert(r);
        }
        else
        {
            L.erase(L.find(l)), R.erase(R.find(r));
            lt[r].erase(lt[r].find(l)), rt[l].erase(rt[l].find(r));
        }
        tr.reupdate(l), tr.reupdate(r);
        if (*begin(R) <= *rbegin(L))
            cout << tr.get();
        else
            cout << *begin(rt[*rbegin(L)]) - *rbegin(lt[*begin(R)]);
        cout << '\n';
    }
    return 0;
}
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号