首页 > 其他分享 >矩形面积并 - 扫描线模板

矩形面积并 - 扫描线模板

时间:2024-10-06 21:22:34浏览次数:12  
标签:cnt int ll xx 扫描线 x2 line 矩形 模板

扫描线模板(矩形面积并)

首先离散化的思想,将各个线段细分到单位长,于是就是动态求当前值域内 tag \(> 1\) 的数量。

以下是参考代码,十分优美

int n, cnt;
ll xx[N];
struct Scanline{
    ll y;
    ll lx, rx;
    int inout;
    bool operator < (const Scanline &t) const{
        return y < t.y;
    }
}line[N];
void lineadd(ll yt, ll lxt, ll rxt, int inoutt, int count){
    line[count].inout = inoutt;
    line[count].y = yt;
    line[count].lx = lxt;
    line[count].rx = rxt;
}
int ls(int p){return p << 1;}
int rs(int p){return p << 1|1;}
struct SegmentTree{
    ll tree[N << 2|1];
    int tag[N << 2 |1];
    inline void push_up(int p, int pl, int pr){
        // 向上传递节点,更新节点值
        if(tag[p]){
            tree[p] = xx[pr] - xx[pl];
        }else if(pl + 1 == pr){
            tree[p] = 0;
        }else{
            tree[p] = tree[ls(p)] + tree[rs(p)];
        }
    }

    inline void update(int L, int R, int p, int pl, int pr, int inoutt){
        if(L <= pl && pr <= R){
            tag[p] += inoutt;
            push_up(p, pl, pr);
            return ;
        }
        if(pl + 1 == pr) return ;
        int mid = (pl + pr) >> 1;
        if(L <= mid){
            update(L, R, ls(p), pl, mid, inoutt);
        }
        if(R >= mid + 1){
            update(L, R, rs(p), mid, pr, inoutt); // 注意不是 mid + 1,因为连续性
        }
        push_up(p, pl, pr);
    }

};
SegmentTree seg;

void solve() {
    cin >> n;
    ll x1, x2, y1, y2;
    for(int i = 1; i <= n; i++){
        cin >> x1 >> y1 >> x2 >> y2;
        lineadd(y1, x1, x2, 1, ++cnt);
        xx[cnt] = x1;
        lineadd(y2, x1, x2, -1, ++cnt);
        xx[cnt] = x2;
    }
    sort(xx + 1, xx + 1 + cnt);
    sort(line + 1, line + 1 + cnt);
    int xlen = unique(xx + 1, xx + 1 + cnt) - (xx + 1);
    ll ans = 0;
    for(int i = 1; i <= cnt; i++){
        ans += seg.tree[1]*(line[i].y - line[i - 1].y);
        int L = lower_bound(xx + 1, xx + 1 + xlen, line[i].lx) - xx;
        int R = lower_bound(xx + 1, xx + 1 + xlen, line[i].rx) - xx;
        seg.update(L, R, 1, 1, xlen, line[i].inout);
    }
    cout << ans << "\n";
}

标签:cnt,int,ll,xx,扫描线,x2,line,矩形,模板
From: https://www.cnblogs.com/9102qyy/p/18449433

相关文章

  • C++ 模板详解(一)
    C++模板模板是C++支持参数化多态的工具,使用模板可以使用户为类或者函数声明一种一般模式,使得类中的某些数据成员或者成员函数的参数、返回值取得任意类型。模板是一种对类型进行参数化的工具;通常有两种形式:函数模板和类模板;函数模板针对仅参数类型不同的函......
  • 模板设计模式
    模板设计模式是一种行为设计模式,它在一个方法中定义了一个算法的骨架,而将一些步骤的实现延迟到子类中。结构抽象类(AbstractClass)定义了模板方法(TemplateMethod),它包含了算法的骨架,通常是一个final方法,以防止子类重写整个算法流程。同时定义了一些抽象方法(AbstractMethod),这......