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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章