扫面线+线段树(hdu1542)

Posted wa007

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了扫面线+线段树(hdu1542)相关的知识,希望对你有一定的参考价值。

之前写过这个算法,时间长了就忘掉了,,现在不看书自己努力回想起来,对算法的理解,对线段树的理解感觉也更深了一点(可能心理作用,哈哈哈)

思路简单说一下吧

从做到右遍历每一条矩阵的边(左右边),看该边对右边的面积贡献是正还是负(矩阵左边为正,右边为负),在y轴上用线段树维护在y轴的贡献值,与x轴上该边与下一条边的差值相乘即可

  1 // acm1.cpp: 定义控制台应用程序的入口点。
  2 //
  3 #include<iostream>
  4 #include<cstdio>
  5 #include<cmath>
  6 #include<queue>
  7 #include<vector>
  8 #include<string.h>
  9 #include<cstring>
 10 #include<algorithm>
 11 #include<set>
 12 #include<map>
 13 #include<fstream>
 14 #include<cstdlib>
 15 #include<ctime>
 16 using namespace std;
 17 typedef long long ll;
 18 typedef long long lint;
 19 const ll mod=1e9+7;
 20 const int maxn=1e2+7;
 21 const int maxm=1e5+7;
 22 const double eps=1e-3;
 23 int ar1[maxn],ar2[maxn],m,n;
 24 bool bo[maxn];
 25 struct line{
 26     double y1,y2,x;
 27     int ma;
 28 }li[maxn*2];
 29 
 30 struct node{
 31     int l,r;
 32     int mark;
 33     double length;
 34 }no[maxn*8];
 35 double xl[maxn],yl[maxn];
 36 bool cmp(line l1,line l2){
 37     return l1.x<l2.x;
 38 }
 39 void build(int x,int y,int o){
 40     no[o].l=x;
 41     no[o].r=y;
 42     no[o].length=0;
 43     no[o].mark=0;
 44     if(y-x==1)return ;
 45     int mid=(x+y)>>1;
 46     if(mid>x)build(x,mid,o*2);
 47     if(mid<y)build(mid,y,o*2+1);
 48 }
 49 void down(int x){
 50     if(no[x].mark>0)no[x].length=yl[no[x].r]-yl[no[x].l];
 51     else if(no[x].r==no[x].l+1){
 52         no[x].length=0;
 53     }
 54     else{
 55         no[x].length=no[x*2].length+no[x*2+1].length;
 56     }
 57 }
 58 void update(int o,line & liMid){
 59     double func1=yl[no[o].l],func2=yl[no[o].r];
 60     if(liMid.y1<=func1&&liMid.y2>=func2){
 61         no[o].mark+=liMid.ma;
 62     }
 63     else{
 64         double funcMid=yl[(no[o].l+no[o].r)>>1];
 65         if(liMid.y1<funcMid)update(o*2,liMid);
 66         if(liMid.y2>funcMid)update(o*2+1,liMid);
 67     }
 68     down(o);
 69 }
 70 int main()
 71 {
 72     int fir=0;
 73     while(~scanf("%d",&n)&&n){
 74         for(int i=0;i<n;i++){
 75             double x1,x2,y1,y2;
 76             scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
 77             li[i*2].x=x1;
 78             li[i*2].y1=y1;
 79             li[i*2].y2=y2;
 80             li[i*2].ma=1;
 81             li[i*2+1].x=x2;
 82             li[i*2+1].y1=y1;
 83             li[i*2+1].y2=y2;
 84             li[i*2+1].ma=-1;
 85             yl[i*2]=y1;
 86             yl[i*2+1]=y2;
 87         }
 88         sort(li,li+2*n,cmp);
 89         sort(yl,yl+2*n);
 90         int len=unique(yl,yl+2*n)-yl;
 91         build(0,len-1,1);
 92         double ans=0;
 93         for(int i=0;i<2*n-1;i++){
 94             update(1,li[i]);
 95             ans+=no[1].length*(li[i+1].x-li[i].x);
 96         }
 97         printf("Test case #%d
Total explored area: %.2lf

",++fir,ans);
 98     }
 99     return 0;
100 }

 

以上是关于扫面线+线段树(hdu1542)的主要内容,如果未能解决你的问题,请参考以下文章

hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积

hdu1542线段树(扫描线+离散化)

线段树扫描线(hdu1542)

HDU1542 矩形面积并 扫描线段树

HDU-1542 Atlantis 线段树+扫描线

HDU - 1542 Atlantis (扫描线+线段树)