Hdu 1255 覆盖的面积 线段树+矩形面积并
2013-08-27 13:40
495 查看
继续面积并学习中。。。(线段树解决)
题意:给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积
思路:其实跟求矩形面积并的思想是一样的,只不过在update里做了一点修改,矩形面积并只需要求至少覆盖一次的面积,而这题是至少覆盖两次的面积,稍微做点修改就可以了
一样的,要求面积,就要求出至少覆盖两次的有效长度乘以高度差即可,求有效长度:
1.cnt>1 : 说明该区间被覆盖两次或以上,那么长度就可以直接计算,就是该区间的长度
剩下的情况就是cnt=1或cnt=0
2.先看叶子节点,因为是叶子没有孩子了,所以被覆盖两次货以上的长度就是0(无论cnt=1或cnt=0都是0,因为是叶子。。。)
3.不是叶子节点 ,且cnt=1.注意这里,cnt=1确切的意义是什么,应该是,可以确定,这个区间被完全覆盖了1次,而有没有被完全覆盖两次或以上则不知道无法确定,那么怎么怎么办了,只要加上sum1[左孩子]+sum1[右孩子] 即看看左右孩子区间被覆盖了一次或以上的长度,那么叠加在双亲上就是双亲被覆盖两次或以上的长度
4.不是叶子节点,且cnt=0,确切的意义应该是不完全不知道被覆盖的情况(不知道有没有被覆盖,被覆盖了几次,长度是多少都不知道),这种情况,只能由其左右孩子的信息所得
sum2[左孩子]+sum2[右孩子] , 即直接将左右孩子给覆盖了两次或以上的长度加起来,这样才能做到不重不漏
这里:我用sum1代表至少被覆盖一次的有效长度,sum2代表至少覆盖两次的有效长度
代码:
题意:给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积
思路:其实跟求矩形面积并的思想是一样的,只不过在update里做了一点修改,矩形面积并只需要求至少覆盖一次的面积,而这题是至少覆盖两次的面积,稍微做点修改就可以了
一样的,要求面积,就要求出至少覆盖两次的有效长度乘以高度差即可,求有效长度:
1.cnt>1 : 说明该区间被覆盖两次或以上,那么长度就可以直接计算,就是该区间的长度
剩下的情况就是cnt=1或cnt=0
2.先看叶子节点,因为是叶子没有孩子了,所以被覆盖两次货以上的长度就是0(无论cnt=1或cnt=0都是0,因为是叶子。。。)
3.不是叶子节点 ,且cnt=1.注意这里,cnt=1确切的意义是什么,应该是,可以确定,这个区间被完全覆盖了1次,而有没有被完全覆盖两次或以上则不知道无法确定,那么怎么怎么办了,只要加上sum1[左孩子]+sum1[右孩子] 即看看左右孩子区间被覆盖了一次或以上的长度,那么叠加在双亲上就是双亲被覆盖两次或以上的长度
4.不是叶子节点,且cnt=0,确切的意义应该是不完全不知道被覆盖的情况(不知道有没有被覆盖,被覆盖了几次,长度是多少都不知道),这种情况,只能由其左右孩子的信息所得
sum2[左孩子]+sum2[右孩子] , 即直接将左右孩子给覆盖了两次或以上的长度加起来,这样才能做到不重不漏
这里:我用sum1代表至少被覆盖一次的有效长度,sum2代表至少覆盖两次的有效长度
代码:
#include <iostream> #include <stdio.h> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <map> #include <queue> #define lson l,mid,num<<1 #define rson mid+1,r,num<<1|1 using namespace std; const int M=2010; double sum1[M<<2],sum2[M<<2]; int cnt[M<<2]; double x[M]; struct node { double l,r,h; int flag; node() {} node(double x1,double x2,double y,int s) :l(x1),r(x2),h(y),flag(s) {} bool operator <(const node& rsh)const { return h<rsh.h; } } line[M]; int Bin(double key,int n,double x[]) { int l=0,r=n-1; while(l<=r) { int mid=(l+r)>>1; if(x[mid]==key)return mid; else if(x[mid]<key)l=mid+1; else r=mid-1; } return -1; } //void build(int l,int r,int num) //{ // sum1[num]=sum2[num]=cnt[num]=0; // if(l==r) // return; // int mid=(l+r)>>1; // build(lson); // build(rson); //} void PushUp(int num,int l,int r) { if(cnt[num]) sum1[num] = x[r+1]-x[l]; else if(l==r)sum1[num]=0;//判断叶子结点,只要是叶子结点就都为0 else sum1[num]=sum1[num<<1]+sum1[num<<1|1]; if(cnt[num]>1)sum2[num]=x[r+1]-x[l]; else if(l==r)sum2[num]=0;//判断叶子结点,只要是叶子结点就都为0 else if(cnt[num]==1) sum2[num]=sum1[num<<1]+sum1[num<<1|1]; else sum2[num]=sum2[num<<1]+sum2[num<<1|1]; } void update(int L,int R,int flag,int l,int r,int num) { if(L<=l && r<=R) { cnt[num]+=flag; PushUp(num,l,r); return; } int mid=(l+r)>>1; if(L<=mid)update(L,R,flag,lson); if(R>mid)update(L,R,flag,rson); PushUp(num,l,r); } int main() { int t,n; scanf("%d",&t); while(t--) { double x1,x2,y2,y1; scanf("%d",&n); int st=0; while(n--) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); x[st]=x1; line[st++]=node(x1,x2,y1,1); x[st]=x2; line[st++]=node(x1,x2,y2,-1); } sort(x,x+st); sort(line,line+st); int k=1; for(int i=1; i<st; i++) { if(x[i]!=x[i-1])x[k++]=x[i]; } //build(0,k-1,1); memset(sum1,0,sizeof(sum1)); memset(sum2,0,sizeof(sum2)); memset(cnt,0,sizeof(cnt)); double ret=0; for(int i=0; i<st-1; i++) { int lx=Bin(line[i].l,k,x); int rx=Bin(line[i].r,k,x)-1; if(lx<=rx)update(lx,rx,line[i].flag,0,k-1,1); ret+=sum2[1]*(line[i+1].h-line[i].h); } printf("%.2lf\n",ret); } return 0; }
相关文章推荐
- HDU 1255 覆盖的面积 (扫描线 线段树 离散化 矩形面积并)
- HDU-1255 覆盖的面积 (线段树 求矩形覆盖面积)
- HDU - 1255 覆盖的面积(线段树-矩形交面积)
- HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)
- hdu1255 覆盖的面积 线段树+里离散化求矩形面积的交
- HDU 1255 覆盖的面积(线段树求矩形面积交)
- HDU 1255 矩形覆盖面积(线段树)
- Hdu 1542 Atlantis + Hdu 1255 覆盖的面积 (线段树矩形面积并)
- HDU 1255 - 覆盖的面积 (线段树 扫描线 面积交)
- HDU - 1255 覆盖的面积(线段树 扫描线)
- hdu 1255 覆盖的面积(线段树+扫描线——面积交)
- HDU 1255 覆盖的面积 (线段树 + 离散化 + 扫描线)
- hdu 1255 覆盖的面积 (线段树处理面积覆盖问题(模板))
- HDU 1255 覆盖的面积[离散化 + 扫描线 + 线段树]
- 算法总结:【线段树+扫描线】&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828)
- HDU - 1255 - 覆盖的面积(线段树)
- HDU-1255 覆盖的面积(线段树扫描线模板+离散化+加点修改题)
- hdu 1255 覆盖的面积(线段树+扫描线——面积交)
- HDU 1255 覆盖的面积(线段树+离散化+扫描线)
- hdu 1255 覆盖的面积(线段树+扫描线——面积交)