hdu 1542--线段树扫描线
http://acm.hdu.edu.cn/showproblem.php?pid=1542
题意:矩形面积并
思路:浮点数先要离散化;然后把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用cnt表示该区间下边比上边多几个,sum代表该区间内被覆盖的线段的长度总和
这里线段树的一个结点并非是线段的一个端点,而是该端点和下一个端点间的线段,所以题目中r+1,r-1的地方可以自己好好的琢磨一下

1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 #define maxn 22222 7 #define lson l,m,rt<<1 8 #define rson m+1,r,rt<<1|1 9 double sum[maxn<<2],X[maxn]; 10 int cnt[maxn<<2]; 11 struct node{ 12 double l,r,h; 13 int f; 14 node(){} 15 node(double a,double b,double c,int d):l(a),r(b),h(c),f(d){} 16 bool operator <(const node &cmp) const{ 17 return h<cmp.h; 18 } 19 }ss[maxn]; 20 void Pushup(int l,int r,int rt) 21 { 22 if(cnt[rt]) sum[rt]=X[r+1]-X[l]; 23 else if(l==r) sum[rt]=0; 24 else sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 25 } 26 void update(int L,int R,int c,int l,int r,int rt) 27 { 28 if(L<=l&&r<=R) 29 { 30 cnt[rt]+=c; 31 Pushup(l,r,rt); 32 return; 33 } 34 int m=(l+r)>>1; 35 if(L<=m) update(L,R,c,lson); 36 if(R>m) update(L,R,c,rson); 37 Pushup(l,r,rt); 38 } 39 int Bin(double k,int n,double *X) 40 { 41 int l=0,r=n-1; 42 while(l<=r) 43 { 44 int m=(l+r)>>1; 45 if(X[m]==k) return m; 46 else if(X[m]<k) l=m+1; 47 else r=m-1; 48 } 49 return -1; 50 } 51 int main() 52 { 53 int t,i,cas=1; 54 while(~scanf("%d",&t),t) 55 { 56 int m=0; 57 while(t--) 58 { 59 double a,b,c,d; 60 scanf("%lf%lf%lf%lf",&a,&b,&c,&d); 61 X[m]=a; 62 ss[m++]=node(a,c,b,1); 63 X[m]=c; 64 ss[m++]=node(a,c,d,-1); 65 } 66 sort(X,X+m); 67 sort(ss,ss+m); 68 int n=1; 69 for(i=1;i<m;i++) 70 if(X[i]!=X[i-1]) 71 X[n++]=X[i]; 72 memset(sum,0,sizeof(sum)); 73 memset(cnt,0,sizeof(cnt)); 74 double ret=0; 75 for(i=0;i<m-1;i++) 76 { 77 int l=Bin(ss[i].l,n,X); 78 int r=Bin(ss[i].r,n,X)-1; 79 if(l<=r) 80 update(l,r,ss[i].f,0,n-1,1); 81 ret+=sum[1]*(ss[i+1].h-ss[i].h); 82 } 83 printf("Test case #%d\nTotal explored area: %.2lf\n\n",cas++,ret); 84 } 85 return 0; 86 }
posted on 2013-02-19 13:50 acoderworld 阅读(91) 评论(0) 收藏 举报