刚开始想手写平衡树来着,但是发现其实没必要,因为插入操作很友好。
对每个位置维护一个初始位置的值以及末尾位置的值,插入之前和当前位置的末尾值差一下加入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