poj1177 Picture 2011-12-20

Picture

Time Limit: 2000MSMemory Limit: 10000K

Total Submissions: 7599Accepted: 4014

Description

 

A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. Their sides are all vertical or horizontal. Each rectangle can be partially or totally covered by the others. The length of the boundary of the union of all rectangles is called the perimeter. 

 

Write a program to calculate the perimeter. An example with 7 rectangles is shown in Figure 1. 

 

 

The corresponding boundary is the whole set of line segments drawn in Figure 2. 

 

 

The vertices of all rectangles have integer coordinates. 

Input

 

Your program is to read from standard input. The first line contains the number of rectangles pasted on the wall. In each of the subsequent lines, one can find the integer coordinates of the lower left vertex and the upper right vertex of each rectangle. The values of those coordinates are given as ordered pairs consisting of an x-coordinate followed by a y-coordinate. 

 

0 <= number of rectangles < 5000 

All coordinates are in the range [-10000,10000] and any existing rectangle has a positive area.

Output

 

Your program is to write to standard output. The output must contain a single line with a non-negative integer which corresponds to the perimeter for the input rectangles.

Sample Input

 

7

-15 0 5 10

-5 8 20 25

15 -4 24 14

0 -6 16 4

2 15 10 22

30 10 36 20

34 0 40 16

Sample Output

 

228

Source

 

IOI 1998

 

 

 

_________________________________________

给一些矩形,求周长并。

_________________________________________

和面积并类似,需要将横坐标做一遍线段树,纵坐标做一遍线段树。

_________________________________________

  1 Program Stone;
  2 
  3 var n,left,right,ser,lc,rc:longint;
  4 
  5     ans:int64;
  6 
  7     x1,x2,y1,y2:array[1..5000]of longint;
  8 
  9     s,q,o:array[0..20000]of longint;
 10 
 11     a,b:array[1..100000]of longint;//a表示该区间被覆盖的长度。b表示该整个区间被几个矩形覆盖。
 12 
 13  
 14 
 15  procedure kp(t,w:longint);
 16 
 17  var i,j,k,mid,fuck:longint;
 18 
 19   begin
 20 
 21    i:=t;j:=w;mid:=s[(t+w)div 2];fuck:=q[(t+w)div 2];
 22 
 23    repeat
 24 
 25     while (s[i]<mid)or((s[i]=mid)and(q[i]>fuck)) do inc(i);
 26 
 27     while (s[j]>mid)or((s[j]=mid)and(q[j]<fuck)) do dec(j);
 28 
 29     if i<=j then begin
 30 
 31                    k:=s[i];s[i]:=s[j];s[j]:=k;
 32 
 33                    k:=q[i];q[i]:=q[j];q[j]:=k;
 34 
 35                    k:=o[i];o[i]:=o[j];o[j]:=k;  //排序需要先按坐标大小排,如果坐标相同,则左边优先
 36 
 37                    inc(i);dec(j);
 38 
 39                  end;
 40 
 41    until i>j;
 42 
 43    if i<w then kp(i,w);
 44 
 45    if j>t then kp(t,j);
 46 
 47   end;
 48 
 49  
 50 
 51  procedure update(head,tail,num:longint);  
 52 
 53  var k:longint;
 54 
 55   begin
 56 
 57     k:=(tail+head)div 2;
 58 
 59     if tail+head<=0 then k:=k-1;           //因为坐标有负数。所以计算区间中值需要特别处理。
 60 
 61     if (lc<=head)and(tail<=rc) then
 62 
 63       begin
 64 
 65         b[num]:=b[num]+q[ser];            //q表示左边还是右边。
 66 
 67         if b[num]>0 then a[num]:=tail-head+1;      //若整段区间都被覆盖,则覆盖长度为区间长度。
 68 
 69         if b[num]=0 then a[num]:=a[num*2]+a[num*2+1];//否则为子区间和。
 70 
 71         exit;
 72 
 73       end;
 74 
 75     if lc<=k then update(head,k,num*2);
 76 
 77     if rc>k  then update(k+1,tail,num*2+1);
 78 
 79     if b[num]>0 then a[num]:=tail-head+1;
 80 
 81     if b[num]=0 then a[num]:=a[num*2]+a[num*2+1];
 82 
 83   end;
 84 
 85  
 86 
 87  procedure main;
 88 
 89  var i,k,j:longint;
 90 
 91   begin
 92 
 93     right:=-100000;
 94 
 95     left:=100000;
 96 
 97     for i:=1 to n do
 98 
 99     begin
100 
101      s[i]:=x1[i];s[i+n]:=x2[i];
102 
103      q[i]:=1;q[i+n]:=-1;
104 
105      o[i]:=i;o[i+n]:=i;
106 
107      if y2[i]>right then right:=y2[i];
108 
109      if y1[i]<left then left:=y1[i];
110 
111     end;
112 
113    kp(1,2*n);                         //排序,按顺序加入矩形。
114 
115    for ser:=1 to 2*n do
116 
117     begin
118 
119      lc:=y1[o[ser]];rc:=y2[o[ser]]-1; //目前矩形的边两端。
120 
121      j:=a[1];
122 
123      update(left,right,1);            //修改
124 
125      inc(ans,abs(a[1]-j));            //计算新增的边长。 
126 
127     end;
128 
129   end;
130 
131  
132 
133  procedure init;
134 
135  var i,j:longint;
136 
137   begin
138 
139     readln(n);
140 
141     for i:=1 to n do
142 
143      begin
144 
145       readln(x1[i],y1[i],x2[i],y2[i]);
146 
147      end;
148 
149     main;                           //做纵坐标。
150 
151     fillchar(a,sizeof(a),0);
152 
153     fillchar(b,sizeof(b),0);
154 
155     for i:=1 to n do
156 
157      begin
158 
159       j:=x1[i];x1[i]:=y1[i];y1[i]:=j;
160 
161       j:=x2[i];x2[i]:=y2[i];y2[i]:=j;
162 
163      end;                          //旋转。
164 
165     main;                          //做横坐标。
166 
167   end;
168 
169 Begin
170 
171  assign(input,'input.in');reset(input);
172 
173  assign(output,'output.out');rewrite(output);
174 
175   init;
176 
177   write(ans);
178 
179  close(input);close(output);
180 
181 end.
182 
183  

 

posted on 2016-03-02 17:41  Yesphet  阅读(126)  评论(0编辑  收藏  举报