hdu 1255 覆盖的面积 线段树+离散化+扫描线

题意:给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.

分析:这题跟poj 1151有点相似,只不过多了至少覆盖两次而已。那我们就在原来的基础上改进一下。

一开始的操作,像离散化之类的基本相同,然后在线段树的插入操作中,我们给每个节点新定义了一个值,表示该节点的三种状态:被覆盖了一部分、全部被覆盖和还没被覆盖,然后分情况进行处理,具体方法请看代码,再把被覆盖了两次的加入原来的统计扫描线上边的长度的变量中去,最后统计结果就好啦。

还不懂的就来理解一下代码吧。

代码:

var
  o,l,n,a1,i:longint;
  x1,x2,y1,y2,s,ans:real;
  t:array[1..5000,1..4] of longint;
  a:array[0..3000] of real;
  bian:array[0..3000,1..3] of real;
  b:array[0..3000] 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;
  t[d,4]:=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
  m:=(t[d,1]+t[d,2]) div 2;
  if (a[t[d,1]]=l)and(a[t[d,2]]=r) then
  begin
    if t[d,4]=0
      then begin
             t[d,4]:=2;
             t[d,3]:=t[d,3]+z;
             if t[d,3]=z*2 then s:=s+r-l;
             if t[d,3]=-z then s:=s-r+l;
           end
      else if t[d,4]=1
             then begin
                    insert(d*2,l,a[m],z);
                    insert(d*2+1,a[m],r,z);
                  end
             else begin
                    t[d,3]:=t[d,3]+z;
                    if t[d,3]=z*2 then s:=s+r-l;
                    if t[d,3]=-z then s:=s-r+l;
                  end;
    exit;
  end;
  if t[d,4]=2 then
  begin
    t[d*2,4]:=2;
    t[d*2+1,4]:=2;
    t[d*2,3]:=t[d*2,3]+t[d,3];
    t[d*2+1,3]:=t[d*2+1,3]+t[d,3]; 
  end;
  t[d,4]:=1;
  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(o);
  for l:=1 to o do
  begin
    readln(n);
    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 n*2-1 do
      if a[i]=a[i+1] then
      begin
        a[i]:=maxlongint div 10;
        dec(a1);
      end;
    sort2;
    hehe(1,1,a1);
    i:=1;
    bian[0,1]:=-1;
    bian[n*2+1,1]:=-1;
    s:=0;
    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+s*(bian[i+1,1]-bian[i,1]);
      inc(i);
    end;
    writeln(ans:0:2);
  end;
end.


你可能感兴趣的:(hdu 1255 覆盖的面积 线段树+离散化+扫描线)