poj 1151 Atlantis 线段树+离散化+扫描线

题意:给出n个矩形的左下角和右上角,求所有矩形的总面积(被覆盖的不算)。

分析:这题可以单用离散化来做,不过时间复杂度较高,于是就换用了扫描线。

先把横坐标和纵坐标离散化,然后加边,每次统计扫描线上的边的长度和两条扫描线间的距离就好了。

我说的很简略,连我自己都看不懂。

注意:浮点数之间可以之间判断相等。

我是通过这个网址学会的:

http://blog.csdn.net/youngyangyang04/article/details/7787693

代码:

var
  n,i,a1,tot:longint;
  s,x1,x2,y1,y2,ans:real;
  bian:array[0..300,1..3] of real;
  b:array[0..300] of longint;
  a:array[0..300] of real;
  t:array[1..1000,1..3] of longint;

procedure sort1;
var
  i,j:longint;
begin
  for i:=1 to n*2-1 do
    for j:=i+1 to n*2 do
      if bian[i,1]>bian[j,1] then
      begin
        bian[0]:=bian[i];bian[i]:=bian[j];bian[j]:=bian[0];
        b[0]:=b[i];b[i]:=b[j];b[j]:=b[0];
      end;
end;

procedure sort2;
var
  i,j:longint;
begin
  for i:=1 to n*2-1 do
    for j:=i+1 to n*2 do
      if a[i]>a[j] then
      begin
        a[0]:=a[i];a[i]:=a[j];a[j]:=a[0];
      end;
end;

procedure hehe(d,l,r:longint);
var
  m:longint;
begin
  t[d,1]:=l;
  t[d,2]:=r;
  t[d,3]:=0;
  if r-l=1 then exit;
  m:=(l+r) div 2;
  hehe(d*2,l,m);
  hehe(d*2+1,m,r);
end;

procedure insert(d:longint;l,r:real;z:longint);
var
  m:longint;
begin
  if t[d,2]-t[d,1]=1 then
  begin
    t[d,3]:=t[d,3]+z;
    if t[d,3]=0
      then s:=s-r+l
      else if t[d,3]=z then s:=s+r-l;
    exit;
  end;
  m:=(t[d,1]+t[d,2]) div 2;
  if r<=a[m]
    then insert(d*2,l,r,z)
    else if l>=a[m]
           then insert(d*2+1,l,r,z)
           else begin
                  insert(d*2,l,a[m],z);
                  insert(d*2+1,a[m],r,z);
                end;
end;

begin
  readln(n);
  while n>0 do
  begin
    inc(tot);
    for i:=1 to n do
    begin
      readln(x1,y1,x2,y2);
      bian[i*2-1,1]:=y1;
      bian[i*2-1,2]:=x1;
      bian[i*2-1,3]:=x2;
      b[i*2-1]:=1;
      bian[i*2,1]:=y2;
      bian[i*2,2]:=x1;
      bian[i*2,3]:=x2;
      b[i*2]:=-1;
      a[i*2-1]:=x1;
      a[i*2]:=x2;
    end;
    sort1;
    sort2;
    a1:=n*2;
    for i:=1 to a1-1 do
      if a[i]=a[i+1] then
      begin
        dec(a1);
        a[i]:=maxlongint div 100;
      end;
    sort2;
    hehe(1,1,a1);
    s:=0;
    i:=1;
    bian[0,1]:=-1;
    bian[n*2+1,1]:=-1;
    ans:=0;
    while i<=n*2 do
    begin
      insert(1,bian[i,2],bian[i,3],b[i]);
      while bian[i,1]=bian[i+1,1] do
      begin
        inc(i);
        insert(1,bian[i,2],bian[i,3],b[i]);
      end;
      ans:=ans+(bian[i+1,1]-bian[i,1])*s;
      inc(i);
    end;
    writeln('Test case #',tot);
    writeln('Total explored area: ',ans:0:2);
    writeln;
    readln(n);
  end;
end.


你可能感兴趣的:(poj 1151 Atlantis 线段树+离散化+扫描线)