首页 > 代码库 > HUD 1255——覆盖的面积(线段树+面积并多次+离散化)
HUD 1255——覆盖的面积(线段树+面积并多次+离散化)
覆盖的面积
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3756 Accepted Submission(s): 1846
Problem Description
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
Input
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.
注意:本题的输入数据较多,推荐使用scanf读入数据.
注意:本题的输入数据较多,推荐使用scanf读入数据.
Output
对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.
Sample Input
2 5 1 1 4 2 1 3 3 7 2 1.5 5 4.5 3.5 1.25 7.5 4 6 3 10 7 3 0 0 1 1 1 0 2 1 2 0 3 1
Sample Output
7.63 0.00
——————————————————————分割线————————————
题目大意:
给你n个矩形,求这些矩形相交超过两次的面积和
思路:
原来的面积并是覆盖一次,而这题要求两次以上,自己刚开始并没有区分一次覆盖和两次覆盖的区别!!!
面积并和周长并是区间内或运算!!!
cnt[]表示覆盖次数
对于某个节点:
1:cnt[]>=2表示被完全覆盖,那么长度就等于区间长度
2:叶子节点为0
3:cnt[]==1表示被完全覆盖,但是它的左右子区间如果存在覆盖一次以上的,那么加上这次的,就正好两次以上了,所以要由左右子树的覆盖一次以上的长度得到
4:cnt[]==0 不是表示没有被覆盖,而是没有被完全覆盖,那么要取得覆盖两次以上的,就等于左右子树覆盖两次以上的长度得到
好好理解区间或运算!!!
注意点:
离散化:排序+去重 unique去重函数,返回最后一个元素的迭代器
点化线段——右端点-1
计算长度——线段变回点 右端点+1
写完这个,就去搞体积交3次以上的题目:hdu3642 Get The Treasury
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int maxn=2222; using namespace std; int cnt[maxn<<2]; double sum1[maxn<<2],sum2[maxn<<2]; double X[maxn+10]; struct Seg { double l,r,h; int s; Seg() {}; Seg(double a,double b,double c,double d):l(a),r(b),h(c),s(d) {}; bool operator<(const Seg&cmp)const { return h<cmp.h; } }; Seg ss[maxn+10]; void push_up1(int rt,int l,int r) { if(cnt[rt]) sum1[rt]=X[r+1]-X[l]; else if(l==r) sum1[rt]=0; else sum1[rt]=sum1[rt<<1]+sum1[rt<<1|1]; } void push_up2(int rt,int l,int r) { if(cnt[rt]>=2) sum2[rt]=X[r+1]-X[l]; else if(l==r) sum2[rt]=0; else if(cnt[rt]==1) sum2[rt]=sum1[rt<<1]+sum1[rt<<1|1]; else sum2[rt]=sum2[rt<<1]+sum2[rt<<1|1]; } void update(int L,int R,int c,int l,int r,int rt) { if(L<=l&&r<=R) { cnt[rt]+=c; push_up1(rt,l,r); push_up2(rt,l,r); return ; } int m=(l+r)>>1; if(L<=m) update(L,R,c,lson); if(m<R) update(L,R,c,rson); push_up1(rt,l,r); push_up2(rt,l,r); } void solve(int m) { sort(X,X+m); sort(ss,ss+m); int k=unique(X,X+m)-X; memset(cnt,0,sizeof(cnt)); memset(sum1,0,sizeof(sum1)); memset(sum2,0,sizeof(sum2)); double ret=0; for(int i=0; i<m-1; ++i) { int l=lower_bound(X,X+k,ss[i].l)-X; int r=lower_bound(X,X+k,ss[i].r)-X-1; if(l<=r) update(l,r,ss[i].s,0,k-1,1); ret+=sum2[1]*(ss[i+1].h-ss[i].h); } printf("%.2lf\n",ret); } int main() { int T,n; cin>>T; while(T--) { double x1,y1,x2,y2; int m=0; scanf("%d",&n); while(n--) { scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2); X[m]=x1; ss[m++]=Seg(x1,x2,y1,1); X[m]=x2; ss[m++]=Seg(x1,x2,y2,-1); } solve(m); } return 0; }
HUD 1255——覆盖的面积(线段树+面积并多次+离散化)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。