1. 程式人生 > >hdu1542線段樹(掃描線+離散化)

hdu1542線段樹(掃描線+離散化)

== 參考 .net 傳遞 區間 bool hdu unique xpl

題目鏈接

要求矩形的面積並

代碼不復雜,主要要理解掃描線的思想以及一些細節的處理。

首先需要將接收到的x坐標離散化,方法就是排序去重。接下來的線段樹建立在這個

關於x坐標的數組上,這很關鍵。線段樹的節點代表一段區間,這個區間是由x坐標數組的下標

來構成的。更新的時候就根據水平線段的左右x坐標獲得區間,然後更新區間。

看了這麽多,離散化之後關於r+1,r-1的問題還是很模糊。

我盡力理解一下,有一個[0,4]的區間,葉節點分別為[0,0],[1,1],[2,2],[3,3],[4,4],

那麽[0,0]節點表示的是區間[0,1];[1,1]節點表示的區間[1,2];[2,2]節點表示的區間[2,3];[3,3]節點表示區間[3,4];

當向上傳遞時[0,1]節點表示區間[0,2],以此類推

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=110;//最多矩形個數
struct seg{
    double lx,rx,y;
    short f;
    seg(){}
    seg(double lx_,double rx_,double y_,short f_):lx(lx_),rx(rx_),y(y_),f(f_){}
    bool operator
<(const seg &a)const { return y<a.y; } }; int sgsNum; seg sgs[maxn*2]; int x2nNum; //x2n double x2n[maxn*2]; double len[maxn*8]; int num[maxn*8]; void build(int root,int l,int r) { len[root]=num[root]=0; if(l==r)return; int mid=(l+r)/2; build(root*2,l,mid); build(root
*2+1,mid+1,r); } void pushUp(int root,int l,int r) { if(num[root]){ len[root]=x2n[r+1]-x2n[l]; }else if(l==r){ len[root]=0; } else { len[root]=len[root*2]+len[root*2+1]; } } void update(int root,int L,int R,int f,int l,int r) { if(L<=l&&r<=R){ num[root]+=f; pushUp(root,l,r); return; } int mid=l+(r-l)/2; if(L<=mid)update(root*2,L,R,f,l,mid); if(mid<R)update(root*2+1,L,R,f,mid+1,r); pushUp(root,l,r); } int bin(double k) { int m,l=0,r=x2nNum-1; while(l<=r){ m=(l+r)/2; if(x2n[m]==k)return m; else if(x2n[m]>k)r=m-1; else l=m+1; } return -1; } int main() { //freopen("in.txt","r",stdin); int n,p=0; while(scanf("%d",&n)!=EOF&&n!=0){ sgsNum=0,x2nNum=0; p++; for(int i=0;i<n;i++){ double lx,ly,rx,ry; scanf("%lf%lf%lf%lf",&lx,&ly,&rx,&ry); sgs[sgsNum++]=seg(lx,rx,ly,1); sgs[sgsNum++]=seg(lx,rx,ry,-1); x2n[x2nNum++]=lx; x2n[x2nNum++]=rx; } double area=0; sort(x2n,x2n+x2nNum); sort(sgs,sgs+sgsNum); x2nNum=unique(x2n,x2n+x2nNum)-x2n; build(1,0,x2nNum-1); for(int i=0;i<sgsNum-1;i++){ int l=bin(sgs[i].lx); int r=bin(sgs[i].rx)-1; update(1,l,r,sgs[i].f,0,x2nNum-1); area+=len[1]*(sgs[i+1].y-sgs[i].y); } printf("Test case #%d\n",p); printf("Total explored area: %.2lf\n\n",area); } //while(1); }

參考資料

http://www.cnblogs.com/zhangmingcheng/p/3907072.html

http://blog.csdn.net/qq_37497322/article/details/75126251

hdu1542線段樹(掃描線+離散化)