СГУ 319
Перейти к навигации
Перейти к поиску
Ссылка на задачу
Комментарии
Так как прямоугольники не имеют общих точек, они могут лишь целиком располагаться один внутри другого.
Выполним сжатие координат y → y'. Создадим дерево отрезков с запросом элемента и присвоением на отрезке.
Каждый прямоугольник (включая рамку картины) создаёт два события в координатах xl и xr:
- В координате xl прямоугольник начинается. При помощи дерева отрезков определяется внешний прямоугольник (его индекс присвоен элементу yl' - 1), площадь внешнего прямоугольника уменьшается на площадь текущего прямоугольника. После этого отрезку (yl'; yr' - 1) присваивается индекс текущего прямоугольника.
- В координате xr прямоугольник заканчивается. При помощи дерева отрезков определяется внешний прямоугольник (его индекс присвоен элементу yl' - 1), отрезку (yl'; yr' - 1) присваивается индекс внешнего прямоугольника.
Осталось отсортировать и вывести площади.
Код решения
#include <stdio.h> #include <algorithm> #include <vector> #include <map> using namespace std; class CoordinateCompressor { map<int, int> m; vector<int> v; public: void add(int x) { m[x] = 0; } void build() { for (map<int, int>::iterator i = m.begin(); i != m.end(); i++) { i->second = v.size(); v.push_back(i->first); } } int compress(int x) { return m[x]; } int decompress(int x) { return v[x]; } int count() { return m.size(); } } compressor; class SegmentTree { int size; vector<int> t; int query(int v, int vl, int vr, int pos) { if (t[v] != -1 || vl == vr) return t[v]; int vm = vl + (vr - vl) / 2; if (pos <= vm) return query(2 * v + 1, vl, vm, pos); else return query(2 * v + 2, vm + 1, vr, pos); } void modify(int v, int vl, int vr, int l, int r, int val) { if (r < vl || vr < l) return; if (l <= vl && vr <= r) { t[v] = val; return; } if (t[v] != -1) { t[2 * v + 1] = t[v]; t[2 * v + 2] = t[v]; t[v] = -1; } int vm = vl + (vr - vl) / 2; modify(2 * v + 1, vl, vm, l, r, val); modify(2 * v + 2, vm + 1, vr, l, r, val); } public: SegmentTree() {} SegmentTree(int _size) { size = _size; t = vector<int>(4 * size, -1); } int query(int pos) { if (pos < 0 || pos > size - 1) return -1; return query(0, 0, size - 1, pos); } void modify(int l, int r, int val) { modify(0, 0, size - 1, l, r, val); } } segmentTree; struct Rectangle { int xl, yl, xr, yr; Rectangle(int x1, int y1, int x2, int y2) { xl = min(x1, x2); xr = max(x1, x2); yl = min(y1, y2); yr = max(y1, y2); } long long area() { return ((long long)xr - xl) * (yr - yl); } }; vector<Rectangle> rectangles; long long area[100010]; struct Event { int x, index; Event(int _x, int _index) { x = _x; index = _index; } bool operator < (const Event &that) const { return x < that.x; } void process() { int cyl = compressor.compress(rectangles[index].yl); int cyr = compressor.compress(rectangles[index].yr); int parent = segmentTree.query(cyl - 1); if (x == rectangles[index].xl) { if (parent != -1) area[parent] -= rectangles[index].area(); area[index] = rectangles[index].area(); segmentTree.modify(cyl, cyr - 1, index); } else { if (parent != -1) segmentTree.modify(cyl, cyr - 1, parent); } } }; vector<Event> events; int main() { freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); int n, w, h; scanf("%d%d%d", &n, &w, &h); compressor.add(0); compressor.add(h); rectangles.push_back(Rectangle(0, 0, w, h)); for (int i = 0; i < n; i++) { int x1, y1, x2, y2; scanf("%d%d%d%d", &x1, &y1, &x2, &y2); compressor.add(y1); compressor.add(y2); rectangles.push_back(Rectangle(x1, y1, x2, y2)); } compressor.build(); segmentTree = SegmentTree(compressor.count()); for (int i = 0; i < rectangles.size(); i++) { events.push_back(Event(rectangles[i].xl, i)); events.push_back(Event(rectangles[i].xr, i)); } sort(events.begin(), events.end()); for (int i = 0; i < events.size(); i++) { events[i].process(); } sort(area, area + n + 1); for (int i = 0; i < n + 1; i++) printf("%lld ", area[i]); }