Submission #203465

#TimeUsernameProblemLanguageResultExecution timeMemory
203465faremyPyramid Base (IOI08_pyramid_base)C++14
100 / 100
1844 ms72116 KiB
#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 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...
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...