(***
      PICTURE - PASCAL version 2
      ps@di.fct.unl.pt
 ***)

program Pictures (output);

   type
      pRect = ^rectangle;

      rectangle = record
                    xmin, ymin, xmax, ymax: integer;
                    next: pRect
                  end;

      pEdge = ^edge;

      edge = record             {vertical edges}
               kind: (left, right);
               finish: boolean;
               x, ymin, ymax: integer;
               next: pEdge
             end;

   var
      LRy, R: pRect;    { LRy = list of rectangles }
      LEx: pEdge;
      i, N, yminG, ymaxG, intRect, boundRect: integer;
      f, g: text;
      Perimeter: longint;

   procedure update (ymin, ymax: integer; var yminG, ymaxG: integer);
   begin
      if ymin < yminG then yminG := ymin;
      if ymax > ymaxG then ymaxG := ymax
   end;

   procedure insertRect (var Ly, R: pRect);
      var
         pointer, previous: pRect;
         less: boolean;
   begin
      if Ly = nil then
         begin  R^.next := nil; Ly := R  end
      else
         begin
            less := true;
            pointer := Ly;
            previous := Ly;
            while (pointer <> nil) and less do
               begin
                  if pointer^.ymin >= R^.ymin then less := false
                  else
                     begin
                        previous := pointer;
                        pointer := pointer^.next
                     end
               end;
            if pointer = Ly then Ly := R
            else previous^.next := R;
            R^.next := pointer
         end
   end;

   procedure selectEdges (y: integer; var LRy: pRect; var LEx: pEdge);
      var
         LRAux: pRect;
         E: pEdge;
         greater: boolean;

      procedure insertEdge (E: pEdge; var LEx: pEdge);
         var
            LEAux, previous: pEdge;
            less: boolean;
      begin {ascending order in x}
         if LEx = nil then
            begin  E^.next := nil; LEx := E  end
         else
            begin
               less := true;
               LEAux := LEx;
               previous := LEx;
               while (LEAux <> nil) and less do
                  if LEAux^.x >= E^.x then less := false
                  else
                     begin
                        previous := LEAux;
                        LEAux := LEAux^.next
                     end;
               if LEAux = LEx then LEx := E
               else previous^.next := E;
               E^.next := LEAux
            end
      end;

   begin {selectEdges}
      greater := false;
      while (LRy <> nil) and (not greater) do
         if LRy^.ymin = y then
            begin
               LRAux := LRy;
               new(E);
               E^.kind := left;
               E^.finish := false;
               E^.x := LRy^.xmin;
               E^.ymin := LRy^.ymin;
               E^.ymax := LRy^.ymax;
               insertEdge(E, LEx);
               new(E);
               E^.kind := right;
               E^.finish := false;
               E^.x := LRy^.xmax;
               E^.ymin := LRy^.ymin;
               E^.ymax := LRy^.ymax;
               insertEdge(E, LEx);
               LRy := LRy^.next;
               dispose(LRAux)
            end
         else greater := true
   end;

   procedure deleteEdges (y: integer; var LEx: pEdge);
      var
         aux, prev: pEdge;
         found: boolean;
   begin {delete edges with ymax=y-1; mark edges with ymax=y}
      aux := LEx;  {LEx<>nil }
      repeat
         found := aux^.ymax = y - 1;
         if found then
            begin  aux := aux^.next; dispose(LEx); LEx := aux  end
      until (aux = nil) or (not found);
      prev := aux;
      while aux <> nil do
         if aux^.ymax = y - 1 then
            if prev <> aux then
               begin
                  prev^.next := aux^.next;
                  dispose(aux);
                  aux := prev^.next
               end
            else
               begin
                  LEx := aux^.next;
                  prev := LEx;
                  dispose(aux);
                  aux := LEx
               end
         else
            begin
               aux^.finish := aux^.ymax = y;
               prev := aux;
               aux := aux^.next
            end
   end;

   procedure scanEdges (y: integer; Lx: pEdge);
      var
         intRect, oldIntRect, totalRect, oldTotalRect,
         lowBRect, oldLowBRect, subtR, oldSubtR: integer;
         prev: pEdge;
         first: boolean;
   begin
      intRect := 0;
      oldIntRect := 0;
      totalRect := 0;
      oldTotalRect := 0;
      lowBRect := 0;
      oldLowBRect := 0;
      subtR := 0;
      oldSubtR := 0;
      prev := Lx;
      first := true;
      repeat
         if Lx^.finish then
            if Lx^.kind = left then subtR := subtR + 1
            else subtR := subtR - 1
         else
            begin
               if Lx^.kind = left then
                  begin
                     totalRect := totalRect + 1;
                     if Lx^.ymax > y + 1 then intRect := intRect + 1;
                     if Lx^.ymin = y then lowBRect := lowBRect + 1
                  end
               else    {right edge}
                  begin
                     totalRect := totalRect - 1;
                     if Lx^.ymax > y + 1 then intRect := intRect - 1;
                     if Lx^.ymin = y then lowBRect := lowBRect - 1
                  end;
               if (totalRect = 0) and (oldTotalRect = 1) then
                  Perimeter := Perimeter + 1
               else if (totalRect = 1) and (oldTotalRect = 0) then
                  if not first and (prev^.x = Lx^.x) and not prev^.finish then
                      Perimeter := Perimeter - 1
                  else
                     Perimeter := Perimeter + 1;
               if (oldIntRect = 0) and (oldTotalRect > 0) then
                  Perimeter := Perimeter + Lx^.x - prev^.x;
               if (oldLowBRect > 0) and (oldTotalRect = oldLowBRect) then
                  begin
                     Perimeter := Perimeter + Lx^.x - prev^.x;
                     if oldSubtR > 0 then
                        Perimeter := Perimeter - 2 * (Lx^.x - prev^.x)
                  end
            end;
         oldIntRect := intRect;
         oldTotalRect := totalRect;
         oldLowBRect := lowBRect;
         oldSubtR := subtR;
         first := false;
         prev := Lx;
         Lx := Lx^.next
      until Lx = nil
   end;

begin { MAIN }
   assign(f, 'PICTURE.IN');
   reset(f);
   Perimeter := 0;
   read(f, N);
   new(R);
   with R^ do
      begin
         read(f, xmin, ymin, xmax, ymax);
         yminG := ymin;
         ymaxG := ymax
      end;
   LRy := nil;
   insertRect(LRy, R);
   for i := 2 to N do
      begin
         new(R);
         with R^ do
            begin
               read(f, xmin, ymin, xmax, ymax);
               update(ymin, ymax, yminG, ymaxG)
            end;
         insertRect(LRy, R)
      end;
   close(f);
   LEx := nil;
   for i := yminG to ymaxG do
      begin
         selectEdges(i, LRy, LEx);
         if LEx <> nil then
            begin
               deleteEdges(i, LEx);
               if LEx <> nil then scanEdges(i, LEx);
            end
      end;
   writeln('Perimeter=', Perimeter : 1);
   assign(g, 'PICTURE.OUT');
   rewrite(g);
   writeln(g, Perimeter:1);
   close(g)
end.
