• HDU 1255 覆盖的面积(线段树面积并)


     
    描述
    给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.

    Input
    输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.

    注意:本题的输入数据较多,推荐使用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
    题意
    如上
    题解
    离散化,做线段树面积并
    然后求并两次的,再开个数组sum2表示并两次的面积
    如果col>=2表示rt的面积并了至少2次,sum2[rt]=x[r+1]-x[l]
    如果l==r表面是叶子结点,sum2[rt]=0
    如果col==1表示rt的面积并了一次, 这时我们看它的左右孩子是否被覆盖过,如果有则说明父区间被覆盖了两次,所以sum2[rt]=sum1[rt<<1]+sum1[rt<<1|1]
    如果col==0表示rt的面积没有并,直接sum2[rt]=sum2[rt<<1]+sum2[rt<<1|1]
    代码
     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 
     5 using namespace std;
     6 
     7 const int N=2005;
     8 int col[N<<2];
     9 double sum1[N<<2],sum2[N<<2],x[N<<2];
    10 struct seg
    11 {
    12     double l,r,h;
    13     int s;
    14     seg(){}
    15     seg(double l,double r,double h,int s):l(l),r(r),h(h),s(s){}
    16     bool operator<(const seg &D){
    17         return h<D.h;
    18     }
    19 }a[N];
    20 
    21 void PushUp(int rt,int l,int r)
    22 {
    23     if(col[rt])sum1[rt]=x[r+1]-x[l];
    24     else if(l==r)sum1[rt]=0;
    25     else sum1[rt]=sum1[rt<<1]+sum1[rt<<1|1];
    26 
    27     if(col[rt]>=2)sum2[rt]=x[r+1]-x[l];
    28     else if(l==r)sum2[rt]=0;
    29     else if(col[rt]==1)sum2[rt]=sum1[rt<<1]+sum1[rt<<1|1];
    30     else if(col[rt]==0)sum2[rt]=sum2[rt<<1]+sum2[rt<<1|1];
    31 }
    32 void Update(int L,int R,int C,int l,int r,int rt)
    33 {
    34     if(L<=l&&r<=R)
    35     {
    36         col[rt]+=C;
    37         PushUp(rt,l,r);
    38         return;
    39     }
    40     int mid=(l+r)>>1;
    41     if(L<=mid)Update(L,R,C,l,mid,rt<<1);
    42     if(R>mid)Update(L,R,C,mid+1,r,rt<<1|1);
    43     PushUp(rt,l,r);
    44 }
    45 int main()
    46 {
    47     int t;
    48     scanf("%d",&t);
    49     while(t--)
    50     {
    51         int n,cnt=0;
    52         double x1,x2,y1,y2;
    53         scanf("%d",&n);
    54         for(int i=1;i<=n;i++)
    55         {
    56             scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
    57             a[++cnt]=seg(x1,x2,y1,1);
    58             x[cnt]=x1;
    59             a[++cnt]=seg(x1,x2,y2,-1);
    60             x[cnt]=x2;
    61         }
    62         sort(x+1,x+1+cnt);
    63         sort(a+1,a+1+cnt);
    64         int k=1;
    65         for(int i=2;i<=cnt;i++)
    66             if(x[i]!=x[i-1])
    67                 x[++k]=x[i];
    68         memset(col,0,sizeof(col));
    69         memset(sum1,0,sizeof(sum1));
    70         memset(sum2,0,sizeof(sum2));
    71         double ans=0;
    72         for(int i=1;i<cnt;i++)
    73         {
    74             int l=lower_bound(x+1,x+1+k,a[i].l)-x;
    75             int r=lower_bound(x+1,x+1+k,a[i].r)-x-1;
    76             Update(l,r,a[i].s,1,k,1);
    77             ans+=sum2[1]*(a[i+1].h-a[i].h);
    78         }
    79         printf("%.2f
    ",ans);
    80     }
    81     return 0;
    82 }
  • 相关阅读:
    实战weblogic集群之创建节点和集群
    实战weblogic集群之创建domain,AdminServer
    linux配置端口转发
    Linux系统下用户行为审计
    实战weblogic集群之安装weblogic
    MongoDB主从配置
    安装配置MongoDB
    PHPCMS v9 自定义表单添加验证码验证
    实战Nginx与PHP(FastCGI)的安装、配置与优化
    在线客服兼容谷歌Chrome、苹果Safari、Opera浏览器的修改
  • 原文地址:https://www.cnblogs.com/taozi1115402474/p/9291961.html
Copyright © 2020-2023  润新知