Submission #218120

#TimeUsernameProblemLanguageResultExecution timeMemory
218120extraterrestrialCandies (JOI18_candies)C++14
100 / 100
702 ms46328 KiB
#include <bits/stdc++.h> typedef long long ll; typedef long double ld; using namespace std; #define F first #define S second #define pb push_back #define all(x) (x).begin(), (x).end() #define SZ(x) (int)(x).size() #define int ll mt19937 rnd(239); struct DSU { vector<int> p, l, r; DSU(int n) { p.resize(n + 1); l.resize(n + 1); r.resize(n + 1); iota(all(p), 0); iota(all(l), 0); iota(all(r), 0); } int find(int v) { return p[v] == v ? v : p[v] = find(p[v]); } void merge(int a, int b) { a = find(a), b = find(b); if (a == b) { return; } if (rnd() & 1) { swap(a, b); } p[b] = a; l[a] = min(l[a], l[b]); r[a] = max(r[a], r[b]); } }; struct ST { vector<int> t; void init(int n) { t.resize(4 * n + 10, -1); } void push(int v) { if (t[v] != -1) { t[2 * v] = t[v]; t[2 * v + 1] = t[v]; t[v] = -1; return; } } void update(int v, int l, int r, int a, int b, int vl) { if (l > b || r < a) { return; } if (l >= a && r <= b) { t[v] = vl; return; } push(v); int mid = (l + r) / 2; update(2 * v, l, mid, a, b, vl); update(2 * v + 1, mid + 1, r, a, b, vl); } int get(int v, int l, int r, int need) { if (l == r) { return t[v]; } push(v); int mid = (l + r) / 2; if (need <= mid) { return get(2 * v, l, mid, need); } else { return get(2 * v + 1, mid + 1, r, need); } } /*void init(int n) { t.resize(n + 1); } void update(int v, int l, int r, int a, int b, int vl) { for (int i = a; i <= b; i++) { t[i] = vl; } } int get(int v, int l, int r, int need) { return t[need]; }*/ }; ST tree1, tree2; const int N = 2e5 + 10; int a[N], pref[N]; inline int get_sum(int l, int r) { int rez = pref[r] - pref[l - 1]; if (l % 2 == 0) { rez *= -1; } return rez; } int n; inline int check(int x) { if (x & 1) { return tree1.get(1, 1, n, x); } else { return tree2.get(1, 1, n, x); } } set<int> unmerged[2]; signed main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> n; for (int i = 1; i <= n; i++) { cin >> a[i]; } for (int i = 1; i <= n; i++) { pref[i] = pref[i - 1]; if (i & 1) { pref[i] += a[i]; } else { pref[i] -= a[i]; } } for (int i = 1; i + 2 <= n; i++) { unmerged[i % 2].insert(i); } tree1.init(n); tree2.init(n); DSU kek(n); tree1.update(1, 1, n, 1, n, 0); tree2.update(1, 1, n, 1, n, 0); set<pair<int, int>> can; for (int i = 1; i <= n; i++) { can.insert({a[i], i}); } set<pair<int, pair<int, int>>> can_flip; int all = 0; for (int i = 1; i <= (n + 1) / 2; i++) { pair<int, int> mx = {-1e18, 0}; if (!can.empty()) { mx = *(--can.end()); } pair<int, pair<int, int>> mx2 = {-1e18, {0, 0}}; if (!can_flip.empty()) { mx2 = *(--can_flip.end()); } if (mx.F > mx2.F) { all += mx.F; can.erase(--can.end()); //cout << 1 << ' ' << mx.S << '\n'; if (mx.S > 1 && can.find({a[mx.S - 1], mx.S - 1}) != can.end()) { can.erase({a[mx.S - 1], mx.S - 1}); } if (mx.S < n && can.find({a[mx.S + 1], mx.S + 1}) != can.end()) { can.erase({a[mx.S + 1], mx.S + 1}); } if (mx.S & 1) { tree1.update(1, 1, n, mx.S, mx.S, 1); } else { tree2.update(1, 1, n, mx.S, mx.S, 1); } if (mx.S > 2 && check(mx.S - 2)) { int comp = kek.find(mx.S - 2); if (kek.l[comp] > 1 && kek.r[comp] < n) { can_flip.erase(make_pair(get_sum(kek.l[comp] - 1, kek.r[comp] + 1), make_pair(kek.l[comp], kek.r[comp]))); } unmerged[mx.S % 2].erase(mx.S - 2); kek.merge(mx.S, mx.S - 2); } if (mx.S + 2 <= n && check(mx.S + 2)) { int comp = kek.find(mx.S + 2); if (kek.l[comp] > 1 && kek.r[comp] < n) { can_flip.erase(make_pair(get_sum(kek.l[comp] - 1, kek.r[comp] + 1), make_pair(kek.l[comp], kek.r[comp]))); } unmerged[mx.S % 2].erase(mx.S); kek.merge(mx.S, mx.S + 2); } int comp = kek.find(mx.S); if (kek.l[comp] > 1 && kek.r[comp] < n) { can_flip.insert(make_pair(get_sum(kek.l[comp] - 1, kek.r[comp] + 1), make_pair(kek.l[comp], kek.r[comp]))); } } else { //cout << i << ' ' << 2 << '\n'; all += mx2.F; int L = mx2.S.F, R = mx2.S.S; //cout << L << ' ' << R << '\n'; if (L > 2 && can.find({a[L - 2], L - 2}) != can.end()) { can.erase({a[L - 2], L - 2}); } if (R + 2 <= n && can.find({a[R + 2], R + 2}) != can.end()) { can.erase({a[R + 2], R + 2}); } if (L & 1) { tree1.update(1, 1, n, L, R, 0); tree2.update(1, 1, n, L - 1, R + 1, 1); } else { tree2.update(1, 1, n, L, R, 0); tree1.update(1, 1, n, L - 1, R + 1, 1); } can_flip.erase(--can_flip.end()); L--, R++; for (;;) { auto it = unmerged[L % 2].lower_bound(L); if (it == unmerged[L % 2].end() || *it > R - 2) { break; } kek.merge(*it, *it + 2); unmerged[L % 2].erase(it); //cout << "C " << *it << '\n'; } if (L > 2 && check(L - 2)) { int comp = kek.find(L - 2); if (kek.l[comp] > 1 && kek.r[comp] < n) { can_flip.erase(make_pair(get_sum(kek.l[comp] - 1, kek.r[comp] + 1), make_pair(kek.l[comp], kek.r[comp]))); } unmerged[L % 2].erase(L - 2); kek.merge(L, L - 2); } if (R + 2 <= n && check(R + 2)) { int comp = kek.find(R + 2); if (kek.l[comp] > 1 && kek.r[comp] < n) { can_flip.erase(make_pair(get_sum(kek.l[comp] - 1, kek.r[comp] + 1), make_pair(kek.l[comp], kek.r[comp]))); } unmerged[R % 2].erase(R); kek.merge(R, R + 2); } int comp = kek.find(L); if (kek.l[comp] > 1 && kek.r[comp] < n) { can_flip.insert(make_pair(get_sum(kek.l[comp] - 1, kek.r[comp] + 1), make_pair(kek.l[comp], kek.r[comp]))); } } cout << all << '\n'; /*for (int i = 1; i <= n; i++) { cout << check(i) << ' '; } cout << '\n';*/ } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...