hdu1255 矩形面积二次交

http://acm.hdu.edu.cn/showproblem.php?pid=1255

理解hdu1542后,这题也就改一下就行了。

题意:给出n个矩形的左下角与右上角坐标,求矩形覆盖两次以上的面积

解题思路:

与hdu1542思路一样,将X坐标离散建树再一层一层计算面积,唯一不同在于这里多一个量twoMoreLen,向上更新时维护好twoMoreLen就好

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<bitset>
using namespace std;
#define N 1100
struct line
{
    double left,right,h;
    int flag;
}L[2*N];
map<double,int>M;
double X[2*N];
double XLi[2*N];
int cmp(line aa,line bb)
{
    return aa.h<bb.h;
}
struct node
{
    int left,right,cover;//cover表示该段成段覆盖的次数,但不向下更新
    double oneMoreLen,twoMoreLen;//该区间覆盖一次以上、两次以上的长度
}seg_tree[N*4];
void seg_built(int l,int r,int num)
{
    seg_tree[num].left=l;
    seg_tree[num].right=r;
    seg_tree[num].cover=0;
    seg_tree[num].oneMoreLen=0;
    seg_tree[num].twoMoreLen=0;
    if(r!=l+1)
    {
        int mid=(l+r)>>1;
        seg_built(l,mid,num<<1);
        seg_built(mid,r,num<<1|1);
    }
}
void push_up(int num)//向上更新
{
    if(seg_tree[num].cover>=2)
    {
        seg_tree[num].twoMoreLen=XLi[seg_tree[num].right]-XLi[seg_tree[num].left];
        seg_tree[num].oneMoreLen=XLi[seg_tree[num].right]-XLi[seg_tree[num].left];
        return;
    }
    if(seg_tree[num].cover==1)
    {
        if(seg_tree[num].right==seg_tree[num].left+1)//叶子节点
        {
            seg_tree[num].twoMoreLen=0;
            seg_tree[num].oneMoreLen=XLi[seg_tree[num].right]-XLi[seg_tree[num].left];
        }
        else//非叶子节点,twoMoreLen要看下面的oneMoreLen长度
        {
            seg_tree[num].twoMoreLen=seg_tree[2*num].oneMoreLen+seg_tree[2*num+1].oneMoreLen;
            seg_tree[num].oneMoreLen=XLi[seg_tree[num].right]-XLi[seg_tree[num].left];
        }
        return;
    }
    if(seg_tree[num].right==seg_tree[num].left+1)
    {
        seg_tree[num].oneMoreLen=0;
        seg_tree[num].twoMoreLen=0;
    }
    else
    {
        seg_tree[num].oneMoreLen=seg_tree[2*num].oneMoreLen+seg_tree[2*num+1].oneMoreLen;
        seg_tree[num].twoMoreLen=seg_tree[2*num].twoMoreLen+seg_tree[2*num+1].twoMoreLen;
    }
}
void seg_update(int l,int r,int value,int num)
{
    if(l>=seg_tree[num].right||r<=seg_tree[num].left) return;
    if(l<=seg_tree[num].left&&r>=seg_tree[num].right)
    {
        seg_tree[num].cover+=value;
        push_up(num);
        return;
    }
    seg_update(l,r,value,2*num);
    seg_update(l,r,value,2*num+1);
    push_up(num);
}
int main()
{
    int i,j,k;
    int n,m,t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        M.clear();
        m=0;
        for(i=1;i<=n;i++)
        {
            double x1,x2,y1,y2;
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            X[++m]=x1;
            L[m].left=x1;
            L[m].right=x2;
            L[m].h=y1;
            L[m].flag=1;//线段记录
            X[++m]=x2;
            L[m].left=x1;
            L[m].right=x2;
            L[m].h=y2;
            L[m].flag=-1;//线段记录
        }
        sort(X+1,X+1+m);
        sort(L+1,L+1+m,cmp);
        M[X[1]]=1;
        XLi[1]=X[1];
        j=1;
        for(i=2;i<=m;i++)//X坐标离散化
        {
            if(X[i]!=X[i-1])
            {
                M[X[i]]=++j;
                XLi[j]=X[i];
            }
        }
        seg_built(1,j,1);
        double sum=0;
        for(i=1;i<m;i++)
        {
            seg_update(M[L[i].left],M[L[i].right],L[i].flag,1);
            sum+=seg_tree[1].twoMoreLen*(L[i+1].h-L[i].h);
        }
        printf("%.2lf\n",sum);
    }
}
/*
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
output:
7.63
0.00
*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值