This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#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 time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |