1. 程式人生 > >線段樹+掃描線【bzoj1645】[USACO07OPEN]城市的地平線City Horizon

線段樹+掃描線【bzoj1645】[USACO07OPEN]城市的地平線City Horizon

Description

約翰帶著奶牛去都市觀光。在落日的餘暉裡,他們看到了一幢接一幢的摩天高樓的輪廓在地平線 上形成美麗的圖案。以地平線為 X 軸,每幢高樓的輪廓是一個位於地平線上的矩形,彼此間可能有 重疊的部分。奶牛一共看到了 N 幢高樓,第 i 幢樓的高度是 Hi,兩條邊界輪廓在地平線上的座標是 Ai 到 Bi。請幫助奶牛們計算一下,所有摩天高樓的輪廓覆蓋的總面積是多少。

Input

第一行一個整數N,然後有N行,每行三個正整數ai、bi、Hi。

Output

一個數,數列中所有元素的和。

剛開始被嚇得以為是個二分,發現不會。然後放棄了一段時間。

今天隨機跳題跳到這個,發現這不是裸的掃描線問題咩。 。。

我們對於摩天大樓,記錄其下邊界為\(0\),上邊界即為摩天大樓的高度。

然後最左側座標即為\(a_i\),最右側座標即為\(b_i\)

然後對於橫座標離散化一下,我們直接跑掃描線即可。

PS:記得開\(long \ long\)還有陣列要開大!!

程式碼

#include<cstdio>
#include<iostream>
#include<algorithm>
#define int long long 
#define R register

using namespace std;

const int gz=100008;

inline void in(R int &x)
{
    R int f=1;x=0;char s=getchar();
    while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    x*=f;
}

struct ode
{
    int l,r,h,f;
    bool operator <(const ode&a)const
    {
        return h<a.h;
    }
}edge[gz<<1];

struct cod
{
    int l,r;
    int len,s;
}tr[gz<<2];

int n,x[gz],tot;

#define ls o<<1
#define rs o<<1|1

void build(R int o,R int l,R int r)
{
    tr[o].l=l,tr[o].r=r;
    tr[o].len=tr[o].s=0;
    if(l==r)return;
    R int mid=(l+r)>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
}

inline void up(R int o)
{
    if(tr[o].s)
        tr[o].len=x[tr[o].r+1]-x[tr[o].l];
    else if(tr[o].l==tr[o].r)
        tr[o].len=0;
    else tr[o].len=tr[ls].len+tr[rs].len;
}

void change(R int o,R int l,R int r ,R int k)
{
    if(tr[o].l==l and tr[o].r==r)
    {
        tr[o].s+=k;
        up(o);
        return;
    }
    R int mid=(tr[o].l+tr[o].r)>>1;
    if(r<=mid)change(ls,l,r,k);
    else if(l>mid)change(rs,l,r,k);
    else change(ls,l,mid,k),change(rs,mid+1,r,k);
    up(o);
}

signed main()
{
    in(n);
    for(R int i=1,a,b,c;i<=n;i++)
    {
        in(a),in(b),in(c);
        edge[++tot].l=a,edge[tot].h=0,edge[tot].r=b;
        edge[tot].f=1;x[tot]=a;
        edge[++tot].l=a,edge[tot].h=c;edge[tot].r=b;
        edge[tot].f=-1;x[tot]=b;
    }
    sort(x+1,x+tot+1);
    sort(edge+1,edge+tot+1);
    R int new_n=1;
    for(R int i=2;i<=tot;i++)
        if(x[new_n]!=x[i])
            x[++new_n]=x[i];
    build(1,1,new_n);
    R int ans=0;
    for(R int i=1;i<=tot;i++)
    {
        R int l=lower_bound(x+1,x+new_n+1,edge[i].l)-x;
        R int r=lower_bound(x+1,x+new_n+1,edge[i].r)-x-1;
        change(1,l,r,edge[i].f);
        ans+=(edge[i+1].h-edge[i].h)*tr[1].len;
    }
    printf("%lld",ans);
}