维护集合最值和集合全体加
你有一个可重集合初始有n个数,有4种操作,5e5次操作
- 向集合中加入一个数
- 删除集合中一个数
- 集合中所有数加x
- 查询集合最大值
进一步考虑另一个可以使用这个模型的问题。一个vector,动态在尾部增加数,删除数,边操作边求后缀和最小值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| #include <bits/stdc++.h> #ifdef LOCAL #include "debug.h" #else #define deb(...) #endif using namespace std; #define ll long long
#define ull unsigned long long #define pii pair<int, int> #define db double #define baoliu(x, y) cout << fixed << setprecision(y) << x #define endl "\n" #define alls(x) (x).begin(), (x).end() #define fs first #define sec second #define bug(x) cerr << #x << " = " << x << endl const int N = 2e5 + 10; const int M = 1e6 + 10; const int inf = 0x3f3f3f3f; const int mod = 998244353; const double eps = 1e-8; const double PI = acos(-1.0); void solve() { int n; cin >> n; vector<int> a(n + 1); vector<int> suf(n + 1); for (int i = 1; i <= n; i++) cin >> a[i]; for (int i = n; i >= 1; i--) { if (i == n) suf[i] = a[i]; else suf[i] = suf[i + 1] + a[i]; } multiset<int> st; for (int i = 1; i <= n; i++) st.insert(suf[i]); int offset = 0; int sufsum = suf[1]; auto update = [&](int x) { offset += x; }; auto add = [&](int x) { st.insert(x - offset); }; auto del = [&](int x) { int cur = x - offset; assert(st.find(cur) != st.end()); st.erase(st.find(cur)); }; auto query = [&] { return *prev(st.end()) + offset; }; int m; cin >> m; for (int i = 1; i <= m; i++) { int op; cin >> op; if (op == 1) { int x; cin >> x; sufsum += x; a.push_back(x); update(x); add(sufsum); } else if (op == 2) { int x = a.back(); a.pop_back(); del(sufsum); sufsum -= x; update(-x); } else cout << query() << endl; } }
signed main() { cin.tie(0); ios::sync_with_stdio(false); #ifdef LOCAL double starttime = clock(); #endif int t = 1; while (t--) solve(); #ifdef LOCAL double endtime = clock(); cerr << "Time Used: " << (double)(endtime - starttime) / CLOCKS_PER_SEC * 1000 << " ms" << endl; #endif return 0; }
|
怎么转化的?
假设初始有n个元素 我就把n个后缀和存进集合里。需要维护如下操作: