有些需要说明的地方:
以前写线段树时线段树的每个叶节点为一个数字,代表一个区域 (7 ,代表第七个单位长度区域);
本题不同在于,最小单位区域必须有两点代表(2-3 代表从2到3 的一个区域)
上篇扫描线算法复杂度为o(n^2) 本题用离散化法加线段树优化为nlog(n);
#include <cstring> #include <cstdio> #include <iostream> #include <algorithm> using namespace std; #define lson l,m,rt<<1 #define rson m,r,rt<<1|1 #define INF 1000000100 const int maxn = 210; double ty[maxn]; int kk; int find(double value){ int p=lower_bound(ty+1,ty+kk,value) - ty; //cout<<p<<"-->"<<ty[p]<<endl; return p; } int flag; struct Line{ double x,y1,y2; int side; Line(){} void get(double xx=0,double yy1=0,double yy2=0,int sidee=0){ x=xx; y1=yy1; y2=yy2; side=sidee; } bool operator<(const Line& rhs)const{ return x < rhs.x; } }line[maxn]; struct Warm_house{ double x; double y1,y2; int flag; Warm_house(){} void get(double yy1=0,double yy2=0,int f=0){ y1=yy1; y2=yy2; flag=f; } }warm[maxn<<2]; void build(int l,int r,int rt){ // cout<<rt<<endl; warm[rt].flag=0; warm[rt].y1=ty[l]; warm[rt].y2=ty[r]; if(l==r-1) return ; int m=(l+r)>>1; build(lson); build(rson); } double ans; int ql,qr,fff; double x; void update(int l,int r,int rt){ if(l==r-1){ //if(ql<=l&&r<=qr){ //cout<<l<<" "<<r<<endl; if(warm[rt].flag>0){ ans+=(x-warm[rt].x)*(ty[r]-ty[l]); warm[rt].x=x; warm[rt].flag+=fff; } else { warm[rt].x=x; warm[rt].flag+=fff; } //} return ; } int m=(r+l)>>1; if(ql<m) update(lson); if(qr>m) update(rson); } int main() { int n,kase=1; double x1,y1,x2,y2; while(scanf("%d",&n)==1&&n){ int id=1; for(int i=1;i<=n;i++){ scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2); ty[id]=y1; line[id].get(x1,y1,y2,1); id++; ty[id]=y2; line[id].get(x2,y1,y2,-1); id++; } sort(ty+1,ty+id); sort(line+1,line+id); kk = unique(ty+1,ty+id)-(ty+1); build(1,kk,1); ans=0; for(int i=1;i<id;i++){ double gy1=line[i].y1,gy2=line[i].y2; x=line[i].x; fff=line[i].side; ql=find(gy1); qr=find(gy2); update(1,kk,1); } printf("Test case #%d\nTotal explored area: ",kase++); printf("%.2lf\n\n",ans); } return 0; }