hdu1255 ( 线段树扫描求面积并 )
矩形面积交。线段树的好题,第三次做了~~~
注意:如果题目是连续型线段,二分线段判断条件是l+1==r 那么这里不能是mid+1,因为这里是连续型的mid和mid+1之间也是线段 其他题目中点是离散的123... 左边就是[1,mid],右边是[mid+1,r],中间划分线就是mid和mid+1中间这块(这时这块是没用的~)
ac代码:
#include<bits/stdc++.h> #define per(i,a,b) for(int i=a;i<=b;i++) #define mod 1000000007 using namespace std; typedef long long ll; //#define int long long const int inf =0x3f3f3f3f; const double eps=1e-8; int read(){ char ch=getchar(); int res=0,f=0; while(ch<'0' || ch>'9'){f=(ch=='-'?-1:1);ch=getchar();} while(ch>='0'&&ch<='9'){res=res*10+(ch-'0');ch=getchar();} return res*f; } // ------------------------head const int siz=1005; int T,n; struct Line{ int l,r,v; double x1,x2,y; }line[siz*2]; bool cmp(Line a,Line b){return a.y<b.y;} double point[siz*2]; vector<double>vp; int Enum=0,pnum=0;; void init(){ Enum=0; pnum=0; } struct Node{ //面积并 也就是求>=两条边一起扫过的面积 int l,r,v;//v:重叠次数 double lf,rf;//先记录原来的lf,rf,才能后来对应到离散化的l,r double one,two;//覆盖>=一次/>=两次的长度 }tr[siz*2*4]; void build(int u,int l,int r){ tr[u].l=l;tr[u].r=r; tr[u].lf=point[l];tr[u].rf=point[r]; tr[u].v=0; tr[u].one=tr[u].two=0; if(l==r-1)return; int mid=(l+r)>>1; build(u*2,l,mid); build(u*2+1,mid,r); } void cal(int u){//要考虑到叶子节点和非叶子节点 if(tr[u].v>=2){tr[u].one=tr[u].two=tr[u].rf-tr[u].lf;} else if(tr[u].v==1){ tr[u].one=tr[u].rf-tr[u].lf; if(tr[u].l+1==tr[u].r){tr[u].two=0;} else{tr[u].two=tr[u<<1].one+tr[(u<<1)|1].one;} } else{ if(tr[u].l+1==tr[u].r){tr[u].one=tr[u].two=0;} else { tr[u].one=tr[u<<1].one+tr[(u<<1)|1].one; tr[u].two=tr[u<<1].two+tr[u*2+1].two; } } } void update(int u,int e){//e means the num of line if(line[e].l<=tr[u].l&&line[e].r>=tr[u].r){ tr[u].v+=line[e].v; cal(u); return; } int mid=(tr[u].l+tr[u].r>>1); if(line[e].l<mid)update(u<<1,e); if(line[e].r>mid)update((u<<1)|1,e); cal(u); } signed main() { freopen("Data_In.txt","r",stdin); scanf("%d",&T); double x1,y1,x2,y2; while(T--){ scanf("%d",&n); init(); per(i,1,n){ scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); point[pnum++]=x1;point[pnum++]=x2; line[Enum].x1=x1;line[Enum].x2=x2; line[Enum].v=1;line[Enum++].y=y1; line[Enum].x1=x1;line[Enum].x2=x2; line[Enum].v=-1;line[Enum++].y=y2; } sort(line,line+Enum,cmp); sort(point,point+pnum); pnum=unique(point,point+pnum)-point; per(i,0,Enum-1){//这里离散化重新记录中注意编号 //从0开始编号还是从1开始编号都不用再减1,,,很妙啊!!! line[i].l=lower_bound(point,point+pnum,line[i].x1)-point; line[i].r=lower_bound(point,point+pnum,line[i].x2)-point; } build(1,0,pnum-1); update(1,0); double ans=0; per(i,1,Enum-1){ ans+=(tr[1].two*(line[i].y-line[i-1].y)); update(1,i); } printf("%.2lf\n",ans); } return 0; }

浙公网安备 33010602011771号