线段树的基本姿势。
对所有坐标离散化,扫描的同时打+1/-1标记并累加面积。
线段树每个叶结点i表示i-1~i这段有没有矩形覆盖,维护区间最大值和最小值,当一个区间的最小值>0时,直接加上这个区间;当一个区间的最大值==0时,直接跳过。
最后记住冒号后面有个空格,还有每组数据输出后要空一行。
讲的可能不清楚看代码就好了嘛QwQ
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int MAXN=105;
int n,a[MAXN<<2],ql,qr,kk;
double inp[MAXN<<2],b[MAXN<<2],f[MAXN<<2];
struct Border{
int x,y1,y2,typ;
}p[MAXN<<1];
bool cmp(Border u,Border v){
return u.x<v.x;
}
#define mid ((l+r)>>1)
#define lc (o<<1)
#define rc ((o<<1)|1)
int maxn[MAXN<<4],minn[MAXN<<4],add[MAXN<<4];
void pushdown(int o,int l,int r){
if(!add[o]) return;
maxn[lc]+=add[o];
maxn[rc]+=add[o];
minn[lc]+=add[o];
minn[rc]+=add[o];
add[lc]+=add[o];
add[rc]+=add[o];
add[o]=0;
}
void upd(int o,int l,int r){
if(ql<=l&&r<=qr){
maxn[o]+=kk;
minn[o]+=kk;
add[o]+=kk;
return;
}
pushdown(o,l,r);
if(mid>=ql) upd(lc,l,mid);
if(mid<qr) upd(rc,mid+1,r);
maxn[o]=max(maxn[lc],maxn[rc]);
minn[o]=min(minn[lc],minn[rc]);
}
double query(int o,int l,int r){
if(minn[o]) return f[r]-f[l-1];
pushdown(o,l,r);
double ans=0.0;
if(maxn[lc]) ans+=query(lc,l,mid);
if(maxn[rc]) ans+=query(rc,mid+1,r);
return ans;
}
int main(){
int cas=0;
while(~scanf("%d",&n)){
if(!n) return 0;
cas++;
memset(maxn,0,sizeof maxn);
memset(minn,0,sizeof minn);
memset(add,0,sizeof add);
for(int i=1;i<=(n<<2);i++){
scanf("%lf",&inp[i]);
b[i]=inp[i];
}
sort(b+1,b+(n<<2)+1);
int siz=unique(b+1,b+(n<<2)+1)-b-1;
for(int i=1;i<=(n<<2);i++){
a[i]=lower_bound(b+1,b+siz+1,inp[i])-b;
f[a[i]]=inp[i];
}//离散化。
for(int i=1;i<=n;i++){
int j=i*2-1,k=i*4-3;
p[j].x=a[k];
p[j].y1=a[k+1];
p[j].y2=a[k+3];
p[j].typ=1;
j++;
p[j]=p[j-1];
p[j].x=a[k+2];
p[j].typ=-1;
}//输入矩形的位置。
sort(p+1,p+n*2+1,cmp);
double ans=0.0;
for(int i=1;i<(n<<1);i++){
ql=p[i].y1+1,qr=p[i].y2,kk=p[i].typ;
upd(1,1,n<<2);
double len=query(1,1,n<<2);
ans+=len*(f[p[i+1].x]-f[p[i].x]);
}//扫描。
printf("Test case #%d\nTotal explored area: %.2lf\n\n",cas,ans);
}
}