hdu 3265 Posters 线段树+扫描线

/*
hdu 3265 Posters 线段树+扫描线
用一些中间有矩形洞的矩形海报去糊窗户
文被覆盖的面积

线段树+扫描线
可以简单看一下扫面线,这里只是简单应用(因为边只有水平、垂直两种,所以不用y=y+1地扫,也不用在求交点)

在水平方向上做线段树,进行扫描

每个矩形记录两条边,底边给这段涂上颜色,顶边把颜色去掉

对于大数据,c++的容器的速度还真不敢恭维,以后还是用c吧
改c的时候读x3的时候忘了&

其中还出现几次 Runtime Error(STACK_OVERFLOW)  是因为maxx写成了5555
*/
#include<iostream>
#include<vector>
#include <algorithm>
using namespace std;
const int maxx=55555;
struct node
{
    __int64 sum,color;
}tree[maxx<<3];
struct seg
{
    int x1,x2,y,color;
    seg(int a,int b,int c,int d):x1(a),x2(b),y(c),color(d){}
    bool operator < (const seg &t)const{
        return y < t.y;
    }
};
void pushUp(int no,int l,int r)
{
    if(tree[no].color) tree[no].sum=r-l+1;
    else if(l==r) tree[no].sum=0;
    else tree[no].sum=tree[no<<1].sum+tree[no<<1|1].sum;
}
void update(int x1,int x2,int color,int l,int r,int no)
{
    if(x1<=l&&r<=x2)//整个区间涂上颜色或去掉颜色
    {
        tree[no].color+=color;
        pushUp(no,l,r);//更新所涂长度
        return;
    }
    int m=(l+r)>>1;//左右分别
    if(x1<=m) update(x1,x2,color,l,m,no<<1);//注意等号
    if(x2>m) update(x1,x2,color,m+1,r,no<<1|1);
    pushUp(no,l,r);
}
int main()
{
    int n,x1,x2,x3,x4,y1,y2,y3,y4,i;
    while(cin>>n,n)
    {
        vector<seg> v;
        for(i=1;i<=n;++i)
        {
            cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4;
            if(x1<x3)//拆成四个矩形
            {
                v.push_back(seg(x1,x3,y1,1));//底边给这段涂上颜色,
                v.push_back(seg(x1,x3,y2,-1));//顶边把颜色去掉
            }
            if(x4<x2)
            {
                v.push_back(seg(x4,x2,y1,1));
                v.push_back(seg(x4,x2,y2,-1));
            }
            if(y1<y3)
            {
                v.push_back(seg(x3,x4,y1,1));
                v.push_back(seg(x3,x4,y3,-1));
            }
            if(y4<y2)
            {
                v.push_back(seg(x3,x4,y4,1));
                v.push_back(seg(x3,x4,y2,-1));
            }
        }
        sort(v.begin(),v.end());//从小到大排序,从小的开始扫描
        memset(tree,0,sizeof(tree));
        __int64 ret=0;
        int end=v.size();
        for(i=0;i<end-1;++i)
        {
            if(v[i].x2>v[i].x1)
                update(v[i].x1,v[i].x2-1,v[i].color,0,maxx,1);//对每条边 经行 涂颜色或去颜色  注意第二个参数-1    左闭右开,防止一个点算两次
            ret+=tree[1].sum*(v[i+1].y-v[i].y);//根据所涂长度 及 高度差 算面积

        }
        printf("%I64d\n",ret);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值