Submission #635148

#TimeUsernameProblemLanguageResultExecution timeMemory
635148phathnvRadio Towers (IOI22_towers)C++17
0 / 100
103 ms58936 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, a->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> 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()); } for (auto x : s) { //cerr << x << ' '; } //cerr << endl; 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; int pre = -1; for (int cur : s) { 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 (h[a[1]] == -1 || h[a[3]] == -1) { if (mark[a[1]]) { roots.back() = update(roots.back(), a[1]); mark[a[1]] = false; s.erase(a[1]); } if (mark[a[3]]) { 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]}); } } //cerr << "change " << d << ' ' << l << ' ' << r << endl; for (int i = 0; i < 5; ++i) { //cerr << a[i] << ' '; } //cerr << endl; } } int max_towers(int l, int r, int d) { if (d > changingPoint.back()) { return 1; } 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; } if (h[x] - d >= getMin(root, l, x - 1)) { ++res; } if (h[y] - d >= getMin(root, y + 1, r)) { ++res; } //cerr << "query " << l << ' ' << r << ' ' << d << ' ' << res << endl; return (res + 1) / 2; }

Compilation message (stderr)

towers.cpp: In function 'void init(int, std::vector<int>)':
towers.cpp:114:15: warning: unused variable 'x' [-Wunused-variable]
  114 |     for (auto x : s) {
      |               ^
#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...