学习了一种新的离散化
第一次写有关线段的线段树
个人理解的扫描线:每添加一条边(或权值)就算当前这一部分的东西,然后再添加,一个循环
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> using namespace std; #define MAXN 200 int n,T,t; double x1,x2,y1,y2,ans; struct point{ double x,y1,y2; int flag; }node[2*MAXN]; struct tpoint{ int l,r,s; double len,ml,mr; }tree[4*MAXN]; double y[2*MAXN]; int comp(const point &a,const point &b) { return a.x<b.x+0.00000001; } //tree[p].len表示tree[p].ml~tree[p].mr之间被线段覆盖的总长度 //tree[p].s表示tree[p].ml~tree[p].mr之间被几条线段覆盖 //并且tree[p].s>0表示这条线段被完全覆盖 void build(int p,int l,int r) { tree[p].l=l; tree[p].r=r; tree[p].ml=y[l];//离散化 tree[p].mr=y[r]; tree[p].s=0; tree[p].len=0; if (tree[p].l+1==tree[p].r) return ; int mid=(l+r) >> 1; build(p<<1,l,mid); build(p<<1^1,mid,r); } void callen(int p)//算tree[p].len { if (tree[p].s>0) tree[p].len=tree[p].mr-tree[p].ml; else if (tree[p].l+1==tree[p].r) tree[p].len=0; else tree[p].len=tree[p<<1].len+tree[p<<1^1].len; return ; } void updata(int p,point t) { if (tree[p].ml==t.y1 && tree[p].mr==t.y2) { tree[p].s+=t.flag; callen(p); return ; } double mid=tree[p<<1].mr; if (t.y2<=mid) updata(p<<1,t); if (t.y1>=mid) updata(p<<1^1,t); if (t.y1<mid && t.y2>mid) { point tmp=t; tmp.y2=mid; updata(p<<1,tmp); tmp=t; tmp.y1=mid; updata(p<<1^1,tmp); } callen(p);//每一次更新了tree[p]的子节点,就要更新p的len,保证每次只取tree[1].len即可 return ; } int main() { while (scanf("%d", &n) && (n)) { T++; t=0; for (int i=1;i<=n;i++) { scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2); t++; y[t]=y1; node[t].x=x1; node[t].y1=y1; node[t].y2=y2; node[t].flag=1; t++; y[t]=y2; node[t].x=x2; node[t].y1=y1; node[t].y2=y2; node[t].flag=-1; } sort(node+1,node+t+1,comp); sort(y+1,y+t+1); build(1,1,t); ans=0; updata(1,node[1]); for (int i=2;i<=t;i++) { ans+=(node[i].x-node[i-1].x)*tree[1].len; updata(1,node[i]); } printf("Test case #%d\n",T); printf("Total explored area: %.2lf\n\n",ans); } return 0; }