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 <iostream>
#include <algorithm>
#include <vector>
class Interval
{
int left, right;
public:
Interval(int l, int r) : left(l), right(r) {}
bool IsIncludedIn(const Interval &other) const
{
return (other.left <= left && right <= other.right);
}
bool IsDisjointFrom(const Interval &other) const
{
return (other.right <= left || right <= other.left);
}
Interval Left() const
{
return Interval(left, (left + right) / 2);
}
Interval Right() const
{
return Interval((left + right) / 2, right);
}
int Size() const
{
return (right - left);
}
};
struct Side
{
Side(int p, int l, int r, long long v) : position(p), covers(l, r), value(v) {}
int position;
Interval covers;
long long value;
bool operator <(const Side &other) const
{
return (position < other.position);
}
};
const int MAXP = 4e5;
const int MAXN = 1e6 + 1;
const long long INFTY = 1e18;
const int LEAVES = 1 << 20;
const int TSIZE = LEAVES << 1;
const Interval ROOTCOVER = { 0, LEAVES };
int left[MAXP], bottom[MAXP];
int right[MAXP], top[MAXP];
long long cost[MAXP];
long long minCovering[TSIZE];
long long covering[TSIZE];
std::vector<Side> obstacleLimits;
int on[TSIZE];
int emptyLeft[TSIZE], emptyRight[TSIZE];
int maxEmpty[TSIZE];
std::vector<Side> plus, minus;
void push(int node)
{
if (node < LEAVES)
{
covering[node * 2] += covering[node];
covering[node * 2 + 1] += covering[node];
}
minCovering[node] += covering[node];
covering[node] = 0;
}
void update(int node, Interval covered, Interval requested, long long value)
{
push(node);
if (covered.IsIncludedIn(requested))
{
covering[node] = value;
push(node);
}
else if (!covered.IsDisjointFrom(requested))
{
update(node * 2, covered.Left(), requested, value);
update(node * 2 + 1, covered.Right(), requested, value);
minCovering[node] = std::min(minCovering[node * 2], minCovering[node * 2 + 1]);
}
}
long long getmin(int node, Interval covered, Interval requested)
{
push(node);
if (covered.IsIncludedIn(requested))
return minCovering[node];
if (covered.IsDisjointFrom(requested))
return INFTY;
return std::min(getmin(node * 2, covered.Left(), requested), getmin(node * 2 + 1, covered.Right(), requested));
}
void buildlimits(int squareSize, int obstacles, int width, int height)
{
obstacleLimits.clear();
std::fill_n(minCovering, TSIZE, 0);
std::fill_n(covering, TSIZE, 0);
for (int iObst = 0; iObst < obstacles; iObst++)
{
int trueLeft = std::max(0, left[iObst] - squareSize);
int trueBottom = std::max(0, bottom[iObst] - squareSize);
int trueTop = std::min(height - squareSize + 1, top[iObst]);
obstacleLimits.emplace_back(trueLeft, trueBottom, trueTop, cost[iObst]);
if (right[iObst] < width - squareSize + 1)
obstacleLimits.emplace_back(right[iObst], trueBottom, top[iObst], -cost[iObst]);
}
std::sort(obstacleLimits.begin(), obstacleLimits.end());
}
bool isvalidsize(int squareSize, int obstacles, int width, int height, long long budget)
{
buildlimits(squareSize, obstacles, width, height);
for (int iLim = 0; iLim < (int)obstacleLimits.size();)
{
for (int jLim = iLim; iLim < (int)obstacleLimits.size() && obstacleLimits[iLim].position == obstacleLimits[jLim].position; iLim++)
update(1, ROOTCOVER, obstacleLimits[iLim].covers, obstacleLimits[iLim].value);
if (getmin(1, ROOTCOVER, Interval(0, height - squareSize + 1)) <= budget)
return true;
}
return false;
}
int maxsquare(int smallest, int largest, int obstacles, int width, int height, long long budget)
{
if (smallest == largest)
return 0;
int squareSize = (smallest + largest) / 2;
if (isvalidsize(squareSize, obstacles, width, height, budget))
return std::max(squareSize, maxsquare(squareSize + 1, largest, obstacles, width, height, budget));
return maxsquare(smallest, squareSize, obstacles, width, height, budget);
}
void merge(int node, int size)
{
int l = (on[node * 2] <= 0);
int r = (on[node * 2 + 1] <= 0);
maxEmpty[node] = std::max(std::max(l * maxEmpty[node * 2], r * maxEmpty[node * 2 + 1]), l * emptyRight[node * 2] + r * emptyLeft[node * 2 + 1]);
emptyLeft[node] = l * emptyLeft[node * 2] + (l * emptyLeft[node * 2] == size / 2) * r * emptyLeft[node * 2 + 1];
emptyRight[node] = r * emptyRight[node * 2 + 1] + (r * emptyRight[node * 2 + 1] == size / 2) * l * emptyRight[node * 2];
}
void setup(int width)
{
for (int iLeaf = LEAVES; iLeaf < LEAVES + width; iLeaf++)
{
emptyLeft[iLeaf] = 1;
emptyRight[iLeaf] = 1;
maxEmpty[iLeaf] = 1;
}
int node = LEAVES - 1;
for (int iSize = LEAVES / 2; iSize > 0; iSize /= 2)
for (int iPos = 0; iPos < iSize; iPos++)
{
merge(node, LEAVES / iSize);
node--;
}
}
void add(int node, Interval covered, Interval requested, int val)
{
if (covered.IsIncludedIn(requested))
on[node] += val;
else if (!covered.IsDisjointFrom(requested))
{
add(node * 2, covered.Left(), requested, val);
add(node * 2 + 1, covered.Right(), requested, val);
merge(node, covered.Size());
}
}
int B0(int obstacles, int width, int height)
{
for (int iObst = 0; iObst < obstacles; iObst++)
{
plus.emplace_back(bottom[iObst], left[iObst] - 1, right[iObst], 1);
minus.emplace_back(top[iObst], left[iObst] - 1, right[iObst], -1);
}
std::sort(plus.begin(), plus.end());
std::sort(minus.begin(), minus.end());
setup(width);
int upper = 0, p = 0, m = 0, maxSize = 0;
for (int lower = 0; lower <= height; lower++)
{
while (m < (int)minus.size() && minus[m].position == lower)
{
add(1, ROOTCOVER, minus[m].covers, -1);
m++;
}
while (maxEmpty[1] >= upper - lower && upper <= height)
{
maxSize = std::max(maxSize, upper - lower);
upper++;
while (p < (int)plus.size() && plus[p].position == upper)
{
add(1, ROOTCOVER, plus[p].covers, 1);
p++;
}
}
}
return maxSize;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cout.tie(nullptr);
std::cin.tie(nullptr);
int width, height;
std::cin >> width >> height;
long long budget; std::cin >> budget;
int obstacles; std::cin >> obstacles;
for (int iObst = 0; iObst < obstacles; iObst++)
std::cin >> left[iObst] >> bottom[iObst] >> right[iObst] >> top[iObst] >> cost[iObst];
if (budget == 0)
std::cout << B0(obstacles, width, height) << '\n';
else
std::cout << maxsquare(1, std::min(width, height) + 1, obstacles, width, height, budget) << '\n';
return 0;
}
# | 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... |
# | 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... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |