<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://acm.khpnets.info/w39/index.php?action=history&amp;feed=atom&amp;title=%D0%A1%D0%93%D0%A3_319</id>
	<title>СГУ 319 - История изменений</title>
	<link rel="self" type="application/atom+xml" href="https://acm.khpnets.info/w39/index.php?action=history&amp;feed=atom&amp;title=%D0%A1%D0%93%D0%A3_319"/>
	<link rel="alternate" type="text/html" href="https://acm.khpnets.info/w39/index.php?title=%D0%A1%D0%93%D0%A3_319&amp;action=history"/>
	<updated>2026-05-13T12:35:35Z</updated>
	<subtitle>История изменений этой страницы в вики</subtitle>
	<generator>MediaWiki 1.39.3</generator>
	<entry>
		<id>https://acm.khpnets.info/w39/index.php?title=%D0%A1%D0%93%D0%A3_319&amp;diff=2045&amp;oldid=prev</id>
		<title>Ctrlalt: Новая страница: «== Ссылка на задачу == * [http://acm.sgu.ru/problem.php?problem=319 СГУ #319 &amp;mdash; Kalevich Strikes Back]  == Комментарии == Так …»</title>
		<link rel="alternate" type="text/html" href="https://acm.khpnets.info/w39/index.php?title=%D0%A1%D0%93%D0%A3_319&amp;diff=2045&amp;oldid=prev"/>
		<updated>2016-06-15T23:42:36Z</updated>

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