HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)
生活随笔
收集整理的這篇文章主要介紹了
HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
鏈接:線段樹求矩形面積并 掃描線+離散化
1、給定平面上若干矩形,求出被這些矩形覆蓋過至少兩次的區(qū)域的面積.
2、看完線段樹求矩形面積并 的方法后,再看這題,求的是矩形面積交,類同。
求面積時,用被覆蓋2次以上的那一段乘以掃描線的距離即可,具體實現見代碼。
3、
/* HDU 1255 覆蓋的面積 求矩形面積交(離散化+線段樹) 給定一些矩形 求被這些矩形覆蓋過至少兩次的區(qū)域的面積這里的方法是:線段樹求矩形面積交 掃描線+離散化 左右掃描(x軸掃描),把y軸上的線段離散化 */ #include<iostream> #include<stdio.h> #include<algorithm> #include<string.h> using namespace std;const int MAXN=2005;struct Node {int l,r;//離散化后的y值double lf,rf;//原來的y值,lf代表l原來的y值,rf代表r原來的y值int cnt;//當前段被覆蓋過幾次double lenOnce;//當前段中覆蓋一次以上的長度double lenTwice;//當前段中覆蓋兩次以上的長度 } segTree[MAXN*4]; struct Line {double x;//也就是對應的掃描線x坐標double y1,y2;//線段的端點坐標double f;//1表示一個矩形左邊的邊,-1表示右邊的邊 } line[MAXN];double y[MAXN];bool cmp(Line a,Line b) {return a.x<b.x; }void Build(int i,int l,int r) {segTree[i].l=l;segTree[i].r=r;segTree[i].lenOnce=0;segTree[i].lenTwice=0;segTree[i].lf=y[l];segTree[i].rf=y[r];if(l+1==r)return;int mid=(l+r)>>1;Build(i<<1,l,mid);Build((i<<1)|1,mid,r); } void calen(int i) {if(segTree[i].cnt>=2)//被線段覆蓋次數>=2 {segTree[i].lenOnce=segTree[i].rf-segTree[i].lf;segTree[i].lenTwice=segTree[i].rf-segTree[i].lf;return;}else if(segTree[i].cnt==1)//被線段覆蓋次數==1 {segTree[i].lenOnce=segTree[i].rf-segTree[i].lf;if(segTree[i].l+1==segTree[i].r)segTree[i].lenTwice=0;//當是葉子節(jié)點時else segTree[i].lenTwice=segTree[i<<1].lenOnce+segTree[(i<<1)|1].lenOnce;//因為當前線段被覆蓋過1次,所以覆蓋2次以上的長度是其左右孩子的覆蓋1次以上的長度的和 }else//被線段覆蓋次數==0 {if(segTree[i].l+1==segTree[i].r)//當是葉子節(jié)點時 {segTree[i].lenOnce=segTree[i].lenTwice=0;}else{//因為當前節(jié)點被覆蓋次數為0,所以lenOnce和lenTwice的值由左右孩子決定segTree[i].lenOnce=segTree[i<<1].lenOnce+segTree[(i<<1)|1].lenOnce;segTree[i].lenTwice=segTree[i<<1].lenTwice+segTree[(i<<1)|1].lenTwice;}} } void update(int i,Line e) {if(e.y1==segTree[i].lf&&segTree[i].rf==e.y2){segTree[i].cnt+=e.f;calen(i);//更新當前節(jié)點信息return;}if(e.y2<=segTree[i<<1].rf) update(i<<1,e);else if(e.y1>=segTree[(i<<1)|1].lf) update((i<<1)|1,e);else{Line temp=e;temp.y2=segTree[i<<1].rf;update(i<<1,temp);temp=e;temp.y1=segTree[(i<<1)|1].lf;update((i<<1)|1,temp);}calen(i);//更新當前節(jié)點信息 } int main() {//freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);int T;int n;double x1,y1,x2,y2;scanf("%d",&T);while(T--){scanf("%d",&n);int t=1;for(int i=1; i<=n; i++){scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);//這里題目描述有問題?左下角和右上角line[t].y1=y1;line[t].y2=y2;line[t].x=x1;line[t].f=1;//左邊的邊y[t]=y1;//y坐標離散化(下端點)t++;line[t].y1=y1;line[t].y2=y2;line[t].x=x2;line[t].f=-1;//右邊的邊y[t]=y2;//y坐標離散化(上端點)t++;}sort(line+1,line+t,cmp);//線段按x的值升序排序sort(y+1,y+t);//y坐標從小下到大排序Build(1,1,t-1);//用離散化后的y值(也就是t)建立線段樹 update(1,line[1]);//從第一條掃描線向右掃描double ans=0;for(int i=2; i<t; i++){ans+=segTree[1].lenTwice*(line[i].x-line[i-1].x);update(1,line[i]);}printf("%.2lf\n",ans);}return 0; } View Code?
轉載于:https://www.cnblogs.com/bofengyu/p/4964641.html
總結
以上是生活随笔為你收集整理的HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ubuntu安装搜狗输入法的相关问题
- 下一篇: Redis总结(二)C#中如何使用red