SGU 319. Kalevich Strikes Back (线段树)

319. Kalevich Strikes Back
Time limit per test: 0.5 second(s)
Memory limit: 65536 kilobytes
input: standard
output: standard




And yet again the Berland community can see that talent is always multi-sided. The talent is always seeking new ways of self-expression. This time genius Kalevich amazed everybody with his new painting "Rectangular Frames". The masterpiece is full of impenetrable meaning and hidden themes.

Narrow black rectangular frames are drawn on a white rectangular canvas. No two frames have a common point. Sides of each frame are parallel to the sides of the canvas.

The painting is very big and the reduced replica cannot pass the idea of the original drawing. That's why Kalevich requested that the simplified versions of the masterpiece should be used as replicas. The simplified version is the sequence of the areas of all facets of the original. A facet is a connected enclosed white area within the painting. The areas in the sequence should be written in the non-decreasing order.

Input

The first line of the input contains an integer N (1 ≤ N ≤ 60000) — the number of the frames on the drawing. The second line contains integer numbers W and H (1 ≤ WH ≤ 108).

Let's introduce the Cartesian coordinate system in such a way that the left bottom corner of the canvas has (0, 0) coordinate and the right top corner has the (WH) coordinate. The sides of the canvas are parallel to the axes.

The following N lines contain the description of the frames. Each description is composed of the coordinates of the two opposite corners of the corresponding frame x1y1x2y2(1 ≤ x1x2 < W; 1 ≤ y1y2 < Hx1 != x2y1 != y2). All coordinates are integers. No two frames have a common point.

Output

Write the desired sequence to the output.

Example(s)
sample input
sample output
1
3 3
2 1 1 2
1 8



矩形不相交,可能会内含。

使用线段树的扫描线,搞出保含关系,然后dfs一遍。

  1 /* ***********************************************
  2 Author        :kuangbin
  3 Created Time  :2014/5/1 16:10:22
  4 File Name     :E:\2014ACM\专题学习\数据结构\线段树\SGU319.cpp
  5 ************************************************ */
  6 
  7 #include <stdio.h>
  8 #include <string.h>
  9 #include <iostream>
 10 #include <algorithm>
 11 #include <vector>
 12 #include <queue>
 13 #include <set>
 14 #include <map>
 15 #include <string>
 16 #include <math.h>
 17 #include <stdlib.h>
 18 #include <time.h>
 19 using namespace std;
 20 const int MAXN = 120010;
 21 struct Node
 22 {
 23     int l,r;
 24     int ll,rr;//实际的左右区间
 25     int c;//覆盖标记,懒惰标记
 26 }segTree[MAXN*3];
 27 int x[MAXN];
 28 struct Line
 29 {
 30     int x1,x2,y;
 31     int id;
 32     Line(){}
 33     Line(int _x1,int _x2,int _y,int _id)
 34     {
 35         x1 = _x1;
 36         x2 = _x2;
 37         y = _y;
 38         id = _id;
 39     }
 40 }line[MAXN];
 41 bool cmp(Line a,Line b)
 42 {
 43     return a.y < b.y;
 44 }
 45 void push_down(int r)
 46 {
 47     if(segTree[r].l + 1 == segTree[r].r)return;
 48     if(segTree[r].c != -1)
 49     {
 50         segTree[r<<1].c = segTree[(r<<1)|1].c = segTree[r].c;
 51         segTree[r].c = -1;
 52     }
 53 }
 54 void build(int i,int l,int r)
 55 {
 56     segTree[i].l = l;
 57     segTree[i].r = r;
 58     segTree[i].ll = x[l];
 59     segTree[i].rr = x[r];
 60     segTree[i].c = 0;
 61     if(l+1 == r)return;
 62     int mid = (l+r)/2;
 63     build(i<<1,l,mid);
 64     build((i<<1)|1,mid,r);
 65 }
 66 int pre[MAXN];
 67 void Update(int i,Line e)
 68 {
 69     if(segTree[i].ll == e.x1 && segTree[i].rr == e.x2)
 70     {
 71         if(e.id > 0)
 72             segTree[i].c = e.id;
 73         else segTree[i].c = pre[-e.id];
 74         return;
 75     }
 76     push_down(i);
 77     if(e.x2 <= segTree[i<<1].rr)Update(i<<1,e);
 78     else if(e.x1 >= segTree[(i<<1)|1].ll)Update((i<<1)|1,e);
 79     else
 80     {
 81         Line tmp = e;
 82         tmp.x2 = segTree[i<<1].rr;
 83         Update(i<<1,tmp);
 84         tmp = e;
 85         tmp.x1 = segTree[(i<<1)|1].ll;
 86         Update((i<<1)|1,tmp);
 87     }
 88 }
 89 int query(int i,Line e)
 90 {
 91     if(segTree[i].c != -1)
 92         return segTree[i].c;
 93     if(e.x2 <= segTree[i<<1].rr)return query(i<<1,e);
 94     else if(e.x1 >= segTree[(i<<1)|1].ll)return query((i<<1)|1,e);
 95     else
 96     {
 97         e.x2 = segTree[i<<1].rr;
 98         return query(i<<1,e);
 99     }
100 }
101 long long area[MAXN];
102 vector<int>vec[MAXN];
103 void dfs(int u)
104 {
105     int sz = vec[u].size();
106     for(int i = 0;i < sz;i++)
107     {
108         int v = vec[u][i];
109         area[u] -= area[v];
110         dfs(v);
111     }
112 }
113 
114 int main()
115 {
116     //freopen("in.txt","r",stdin);
117     //freopen("out.txt","w",stdout);
118     int n;
119     int w,h;
120     while(scanf("%d",&n) == 1)
121     {
122         scanf("%d%d",&w,&h);
123         area[0] = (long long)w*h;
124         int x1,x2,y1,y2;
125         int tot = 0;
126         for(int i = 1;i <= n;i++)
127         {
128             scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
129             if(x1 > x2)swap(x1,x2);
130             if(y1 > y2)swap(y1,y2);
131             area[i] = (long long)(x2-x1)*(y2-y1);
132             line[tot] = Line(x1,x2,y1,i);
133             x[tot++] = x1;
134             line[tot] = Line(x1,x2,y2,-i);
135             x[tot++] = x2;
136         }
137         sort(x,x+tot);
138         tot = unique(x,x+tot) - x;
139         build(1,0,tot-1);
140         sort(line,line+2*n,cmp);
141         for(int i = 0;i <= n;i++)
142             vec[i].clear();
143         for(int i = 0;i < 2*n;i++)
144         {
145             if(line[i].id > 0)
146             {
147                 pre[line[i].id] = query(1,line[i]);
148                 vec[pre[line[i].id]].push_back(line[i].id);
149             }
150             Update(1,line[i]);
151         }
152         dfs(0);
153         sort(area,area+n+1);
154         for(int i = 0;i <= n;i++)
155         {
156             printf("%I64d",area[i]);
157             if(i < n)printf(" ");
158             else printf("\n");
159         }
160     }
161     return 0;
162 }

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值