Submission #635257

#TimeUsernameProblemLanguageResultExecution timeMemory
635257phathnvRadio Towers (IOI22_towers)C++17
100 / 100
1507 ms96240 KiB
#include "towers.h" #include <bits/stdc++.h> using namespace std; struct Node { Node* nLeft; Node* nRight; int l, r, sum, minPos, maxPos, minVal; Node(int _l, int _r, int val) { nLeft = nRight = nullptr; l = _l; r = _r; sum = 0; minPos = 1e9; maxPos = -1e9; minVal = val; assert(l <= r); } }; Node* mergeNode(Node* a, Node* b) { assert(a->r + 1 == b->l); Node* res = new Node(a->l, b->r, 1e9); res->nLeft = a; res->nRight = b; res->sum = a->sum + b->sum; res->minPos = min(a->minPos, b->minPos); res->maxPos = max(a->maxPos, b->maxPos); res->minVal = min(a->minVal, b->minVal); return res; } Node* build(int l, int r, const vector<int>& h, const vector<bool>& mark) { if (l == r) { Node* n = new Node(l, r, h[l]); if (mark[l]) { n->sum = 1; n->minPos = n->maxPos = l; } return n; } int mid = (l + r) >> 1; return mergeNode(build(l, mid, h, mark), build(mid + 1, r, h, mark)); } Node* update(Node* n, int pos) { if (pos < n->l || n->r < pos) { return n; } if (n->l == n->r) { assert(n->sum == 1); return new Node(n->l, n->r, n->minVal); } return mergeNode(update(n->nLeft, pos), update(n->nRight, pos)); } int getMin(Node*n, int l, int r) { if (r < n->l || n->r < l) { return 1e9; } if (l <= n->l && n->r <= r) { return n->minVal; } return min(getMin(n->nLeft, l, r), getMin(n->nRight, l, r)); } void get(Node*n, int l, int r, int &x, int &y, int &sum) { if (r < n->l || n->r < l) { return; } if (l <= n->l && n->r <= r) { sum += n->sum; x = min(x, n->minPos); y = max(y, n->maxPos); return; } get(n->nLeft, l, r, x, y, sum); get(n->nRight, l, r, x, y, sum); } int n; vector<int> h; vector<int> type, changingPoint; vector<Node*> roots; void init(int _n, vector<int> _h) { n = _n; h = _h; set<int> s; s.insert(0); for (int i = 1; i < n; ++i) { if (s.size() & 1) { if (h[i] > h[*s.rbegin()]) { s.insert(i); } else { s.erase(*s.rbegin()); s.insert(i); } } else { if (h[i] < h[*s.rbegin()]) { s.insert(i); } else { s.erase(*s.rbegin()); s.insert(i); } } } if (s.size() % 2 == 0) { s.erase(*s.rbegin()); } vector<bool> mark(n, false); for (auto x : s) { mark[x] = true; } changingPoint.push_back(0); roots.push_back(build(0, n - 1, h, mark)); priority_queue<array<int, 3>> pq; type.assign(n, -1); int pre = -1, t = 0; for (int cur : s) { type[cur] = t; t ^= 1; if (pre != -1) { pq.push({-abs(h[pre] - h[cur]), pre, cur}); } pre = cur; } int last = 0; while (!pq.empty()) { auto [d, l, r] = pq.top(); pq.pop(); if (!mark[l] || !mark[r]) { continue; } d = -d; if (d != last) { changingPoint.push_back(d); roots.push_back(roots.back()); last = d; } int a[5] = {-1, -1, -1, -1, -1}; if (h[l] > h[r]) { a[1] = l; a[2] = r; auto it = s.lower_bound(l); if (it != s.begin()) { a[0] = *(--it); } it = s.lower_bound(r); ++it; if (it != s.end()) { a[3] = *it; ++it; } if (it != s.end()) { a[4] = *it; ++it; } } else { a[2] = l; a[3] = r; auto it = s.lower_bound(l); if (it != s.begin()) { a[1] = *(--it); } if (it != s.begin()) { a[0] = *(--it); } it = s.lower_bound(r); ++it; if (it != s.end()) { a[4] = *it; ++it; } } roots.back() = update(roots.back(), a[2]); mark[a[2]] = false; s.erase(a[2]); if (a[1] == -1 || a[3] == -1) { if (a[1] != -1) { roots.back() = update(roots.back(), a[1]); mark[a[1]] = false; s.erase(a[1]); } if (a[3] != -1) { roots.back() = update(roots.back(), a[3]); mark[a[3]] = false; s.erase(a[3]); } } else { if (h[a[1]] > h[a[3]]) { roots.back() = update(roots.back(), a[3]); mark[a[3]] = false; s.erase(a[3]); pq.push({-abs(h[a[1]] - h[a[4]]), a[1], a[4]}); } else { roots.back() = update(roots.back(), a[1]); mark[a[1]] = false; s.erase(a[1]); pq.push({-abs(h[a[0]] - h[a[3]]), a[0], a[3]}); } } } } int max_towers(int l, int r, int d) { Node* root = roots[lower_bound(changingPoint.begin(), changingPoint.end(), d) - changingPoint.begin() - 1]; int x = 1e9, y = -1e9, res = 0; get(root, l, r, x, y, res); if (x > y) { return 1; } assert(type[x] != -1 && type[y] != -1); if (type[x] == 1) { if (h[x] - d >= getMin(root, l, x - 1)) { ++res; } else { --res; } } if (type[y] == 1) { if (h[y] - d >= getMin(root, y + 1, r)) { ++res; } else { --res; } } return max(1, (res + 1) / 2); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...