BZOJ 1058. [ZJOI2007]报表统计

刚开始想手写平衡树来着,但是发现其实没必要,因为插入操作很友好。

对每个位置维护一个初始位置的值以及末尾位置的值,插入之前和当前位置的末尾值差一下加入set,和下一个位置的初始位置的值差一下加入set,删去当前末尾值与下一位置初始值的差即可。

另外一个也用一个set维护。

#include <bits/stdc++.h>

namespace IO {
    void read() {}
    template<class T, class ... T2>
    inline void read(T &x, T2 &... oth) {
        x = 0; T f = 1; char ch = getchar();
        while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
        while (isdigit(ch)) x = x * 10 + ch - 48, ch = getchar();
        x *= f;
        read(oth...);
    }
}

const int N = 5e5 + 7;
const int INF = 0x3f3f3f3f;
int n, m, st[N], ed[N], a[N];
std::multiset<int> appear, ans1;
int ans2;

int main() {
    IO::read(n, m);
    for (int i = 1; i <= n; i++) {
        IO::read(a[i]);
        st[i] = ed[i] = a[i];
        appear.insert(a[i]);
    }
    ans2 = INF;
    std::sort(a + 1, a + 1 + n);
    for (int i = 2; i <= n; i++) {
        ans2 = std::min(ans2, a[i] - a[i - 1]);
        ans1.insert(std::abs(st[i] - st[i - 1]));
    }
    appear.insert(-INF); appear.insert(INF);
    st[0] = ed[0] = st[n + 1] = ed[n + 1] = INF;
    for (int i, k; m--; ) {
        static char opt[100];
        scanf("%s", opt);
        if (opt[0] == 'I') {
            IO::read(i, k);
            ans1.erase(ans1.find(std::abs(st[i + 1] - ed[i])));
            ans1.insert(std::abs(st[i + 1] - k));
            ans1.insert(std::abs(ed[i] - k));
            ed[i] = k;
            std::multiset<int>::iterator it = appear.lower_bound(k);
            ans2 = std::min(ans2, std::abs(*it - k));
            it--;
            ans2 = std::min(ans2, std::abs(*it - k));
            appear.insert(k);
        } else if (opt[4] == 'G') {
            printf("%d\n", *ans1.begin());
        } else {
            printf("%d\n", ans2);
        }
    }
    return 0;
}

/*
3 5
5 3 1
INSERT 2 9
MIN_SORT_GAP
INSERT 2 6
MIN_GAP
MIN_SORT_GAP
*/
View Code

猜你喜欢

转载自www.cnblogs.com/Mrzdtz220/p/12233369.html