扫描线

 

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn=2e5+10;                    //因为一个矩形有两边所以数据范围要乘2

int y[maxn];

struct L
{
    int x;                                //竖边的x坐标
    int y1,y2;                            //竖边的y坐标,y1较小
    int state;                            //是左边还是右边
    bool operator<(const L &b)const       //排序时使用x坐标排序
    {
        return x<b.x;
    }
} line[maxn];

struct node                               //线段树
{
    int l,r;                              //结点区间左右
    int cover;                            //被覆盖次数
    ll len;                               //区间真实长度
} sgt[maxn<<3];                           //注意这个大小

inline void pushup(int k)                 //与普通线段树的区别
{
    if (sgt[k].cover)
    {
        sgt[k].len=sgt[k].r-sgt[k].l;
    }
    else
    {
        sgt[k].len=sgt[k<<1].len+sgt[k<<1|1].len;
    }
}

void build (int rt,int l,int r)
{
    sgt[rt].l=y[l];
    sgt[rt].r=y[r];                         //与普通线段树的区别
    if (r-l<=1) return;                     //与普通线段树的区别

    int mid=(r+l)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid,r);
}

void update(int rt,int x,int y,int z)
{
    int l=sgt[rt].l,r=sgt[rt].r;
    if (x<=l&&r<=y)
    {
        sgt[rt].cover+=z;
        pushup(rt);
        return;
    }
    if (x<sgt[rt<<1].r) update(rt<<1,x,y,z);             //与普通线段树的区别
    if (y>sgt[rt<<1|1].l) update(rt<<1|1,x,y,z);         //与普通线段树的区别
    pushup(rt);
}

int main()
{
    int n;
    scanf("%d",&n);
    for (int i=1,x1,x2,y1,y2; i<=n; i++)
    {
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        y[i]=y1;
        y[i+n]=y2;
        line[i]=L{x1,y1,y2,1};
        line[i+n]=L{x2,y1,y2,-1};
    }
    line[0].x=0;
    sort(y+1,y+1+n*2);
    sort(line+1,line+n*2+1);
    build (1,1,n<<1);
    ull ans=0;               //爆int的毒瘤数据只好用ull处理
    for (int i=1; i<=n<<1; i++)
    {
        ans+=1ull*sgt[1].len*(line[i].x-line[i-1].x);
        update(1,line[i].y1,line[i].y2,line[i].state);
    }
    printf("%llu
",ans);
    return 0;
}

  

原文地址:https://www.cnblogs.com/Accpted/p/11367422.html