扫面线+线段树(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)的主要内容,如果未能解决你的问题,请参考以下文章