HDU1255覆盖的面积

Bryce1010模板

http://acm.hdu.edu.cn/showproblem.php?pid=1255
线段树模板:矩形面积并

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m,r,rt<<1|1
const int MAXN=1e5+10;

double y[MAXN<<2];
struct Line
{
    double x;//记录线段位置
    double y_up,y_down;
    int flag;//左线段为1,右线段为-1
}line[MAXN<<2];

struct Node
{
    double l,r,x;//l维护区间,r维护右区间,x记录上一个x的位置,用于求面积
    bool flag;//标记只有一个区间的节点,将连续的区间离散化为节点
    int cover;//记录覆盖的线段数


}tree[MAXN<<2];

void pushup(int rt)
{
    tree[rt].l=tree[rt>>1].l;
    tree[rt].r=tree[rt>>1|1].r;
}

void build(int l,int r,int rt)
{
    tree[rt].l=y[l];
    tree[rt].r=y[r];
    tree[rt].x=-1;//前一个位置
    tree[rt].flag=false;//不是只有一个区间
    tree[rt].cover=0;
    if(l+1==r)//因为是区间是连续数
    {
        tree[rt].flag=true;//叶子节点
        return;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);//区间是连续的,m不需要+1
}
//flag表示左边线段还是右边线段,碰到左边线段+1,碰到右边线段-1
double query(double l,double r,int rt,double x,int flag)
{
    //如果查找区间不在范围内
    if(l>=tree[rt].r||r<=tree[rt].l)
    {
        return 0;
    }
    //如果是只有一个区间的节点,叶子节点
    if(tree[rt].flag)
    {
        //观察当前范围是否有覆盖区间
        if(tree[rt].cover>1)
        {
            //计算面积
            double pre=tree[rt].x;
            double ans=(x-pre)*(tree[rt].r-tree[rt].l);
            tree[rt].x=x;//更新这个节点,方便下一次计算
            tree[rt].cover+=flag;
            return ans;
        }
        else
        {
            tree[rt].x=x;
            tree[rt].cover+=flag;
            return 0;
        }
    }
    double ans1,ans2;
    ans1=query(l,r,rt<<1,x,flag);
    ans2=query(l,r,rt<<1|1,x,flag);
    return ans1+ans2;
}

bool cmp(Line l1,Line l2)
{
    return l1.x<l2.x;
}

int main()
{
    int t,n;
    double x1,y1,x2,y2;
    cin>>t;
    while(t--)
    {
        cin>>n;
        int cnt=-1;
        for(int i=0;i<n;i++)
        {
            cin>>x1>>y1>>x2>>y2;
            y[++cnt]=y1;
            line[cnt].x=x1;
            line[cnt].y_down=y1;
            line[cnt].y_up=y2;
            line[cnt].flag=1;


            y[++cnt]=y2;
            line[cnt].x=x2;
            line[cnt].y_down=y1;
            line[cnt].y_up=y2;
            line[cnt].flag=-1;
        }
        //将所有高度排序
        sort(y,y+cnt+1);
        //将所有线段排序
        sort(line,line+cnt+1,cmp);
        build(0,cnt,1);
        //扫描线扫描所有的线段
        double area=0;
        for(int i=0;i<=cnt;i++)
        {
            area+=query(line[i].y_down,line[i].y_up,1,line[i].x,line[i].flag);
        }

        printf("%.2f\n",area);

    }


    return 0;
}
posted @ 2018-07-23 09:20  Bryce1010  阅读(93)  评论(0编辑  收藏  举报