漂浮法
以逆序来进行放置,即n to 1。逆序的好处在于放置一个矩形后,俯视看到的就是最终俯视该矩形应该看到的。因为挡着它的矩形在之前已经放置好了,所以可直接统计,为递归创造了条件。每放一个矩形,可以想象成将其扔入一密度很大的海水底部,海分成了n层,然后矩形开始向上浮。在上浮过程中若碰撞到其他的矩形则断裂成几个小矩形,继续上浮,直到浮出水面。于是想到用个递归来模拟上浮过程。
procedure cover(l,r,s,d,k,col:integer); begin while (k<=n) and ((r<=x1[k]) or (l>=x2[k]) or (d<=y1[k]) or (s>=y2[k])) do inc(k); if k>n then begin ans[col]:=ans[col]+(r-l)*(d-s); exit; end; if l<=x1[k] then begin cover(l,x1[k],s,d,k+1,col); l:=x1[k]; end; if r>=x2[k] then begin cover(x2[k],r,s,d,k+1,col); r:=x2[k]; end; if s<=y1[k] then begin cover(l,r,s,y1[k],k+1,col); s:=y1[k]; end; if d>=y2[k] then begin cover(l,r,y2[k],d,k+1,col); d:=y2[k]; end; end;
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iomanip>
using namespace std;
int ans[3000],n;
struct sfaf{int x1;int y1;int x2;int y2;int color;}tu[1010];
void piaofu(int x1,int x2,int y1,int y2,int k,int col);
int main()
{
//freopen("rect1.in","r",stdin);
//freopen("rect1.out","w",stdout);
cin>>tu[0].x2>>tu[0].y2>>n;
tu[0].color=1;
for(int i=1;i<=n;i++)
{
cin>>tu[i].x1>>tu[i].y1>>tu[i].x2>>tu[i].y2>>tu[i].color;
}
for(int i=n;i>=0;i--){
piaofu(tu[i].x1,tu[i].x2,tu[i].y1,tu[i].y2,i+1,tu[i].color);
}
for(int i=1;i<=2500;i++)
if(ans[i]!=0)cout<<i<<" "<<ans[i]<<endl;
return 0;
}
void piaofu(int x1,int x2,int y1,int y2,int k,int col)
{
while((x1>=tu[k].x2||x2<=tu[k].x1||y1>=tu[k].y2||y2<=tu[k].y1)&&k<=n)k++;
if(k==n+1){ans[col]+=(x2-x1)*(y2-y1);return;}
if(x1<tu[k].x1){piaofu(x1,tu[k].x1,y1,y2,k+1,col);x1=tu[k].x1;}
if(x2>tu[k].x2){piaofu(tu[k].x2,x2,y1,y2,k+1,col);x2=tu[k].x2;}
if(y1<tu[k].y1){piaofu(x1,x2,y1,tu[k].y1,k+1,col);y1=tu[k].y1;}
if(y2>tu[k].y2){piaofu(x1,x2,tu[k].y2,y2,k+1,col);y2=tu[k].y2;}
}