Picture usaco5.5 扫描线+线段树+离散

90 篇文章 0 订阅
52 篇文章 0 订阅

Description


给出n个矩形,若某条边的一段被某个矩形覆盖,则这一段就会消失,求剩下的边的总长度。

Solution


那一天wjp终于想起了usaco帐号

咳咳,扫描线+离散+线段树,把一个矩形拆成四条线段做就行了

这里n有5000,线段树一艹到底显然是不行的。那么我们用 Ci 表示i节点被覆盖了多少次, Vi 表示i节点的覆盖状态,0、1、2分别表示完全没覆盖、部分覆盖、全覆盖,然后就a了

实测poj1777不能过,大概是vector的锅

据说暴力扫描是可以的

Code


#include <stdio.h>
#include <vector>
#include <algorithm>
#include <string.h>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define fill(x, t) memset(x, t, sizeof(x))
#define pb push_back
#define N 10001
using namespace std;
struct treeNode{int l, r, c, v;}t[N * 5 + 1];
struct data{int x, ind;};
struct seg{int x, l, r, v;};
int hy[N], lx[N], len;
inline void modify(int now, int l, int r, int v){
    int mid = (t[now].l + t[now].r) >> 1;
    if (t[now].l == l && t[now].r == r){
        if (t[now].v == 0){
            t[now].v = 2;
            t[now].c += v;
            if (!t[now].c || t[now].c == v){
                len += lx[t[now].r] - lx[t[now].l];
            }
        }else if (t[now].v == 1){
            modify(now * 2, l, mid, v);
            modify(now * 2 + 1, mid, r, v);
        }else if (t[now].v == 2){
            t[now].c += v;
            if (!t[now].c || t[now].c == v){
                len += lx[t[now].r] - lx[t[now].l];
            }
        }
        return;
    }
    if (t[now].v == 2){
        t[now * 2].v = t[now * 2 + 1].v = 2;
        t[now * 2].c += t[now].c;
        t[now * 2 + 1].c += t[now].c;
    }
    t[now].v = 1;
    if (r <= mid){
        modify(now * 2, l, r, v);
    }else if (l >= mid){
        modify(now * 2 + 1, l, r, v);
    }else{
        modify(now * 2, l, mid, v);
        modify(now * 2 + 1, mid, r, v);
    }
}
inline void build(int now, int l, int r){
    t[now] = (treeNode){l, r, 0, 0};
    if (l + 1 == r){
        return;
    }
    int mid = (t[now].l + t[now].r) >> 1;
    build(now * 2, l, mid);
    build(now * 2 + 1, mid, r);
}
inline int cmp1(data a, data b){
    return a.x < b.x;
}
inline int cmp2(seg a, seg b){
    return a.x < b.x || a.x == b.x && a.v > b.v;
}
inline void solve(vector<int> u, vector<int> d, vector<int> l, vector<int> r){
    vector<data> p;
    vector<seg> s;
    rep(i, 1, u.size()){
        p.pb((data){l[i - 1], i * 2 - 1});
        p.pb((data){r[i - 1], i * 2});
        s.pb((seg){d[i - 1], i * 2 - 1, i * 2, 1});
        s.pb((seg){u[i - 1], i * 2 - 1, i * 2, -1});
    }
    sort(p.begin(), p.end(), cmp1);
    sort(s.begin(), s.end(), cmp2);
    fill(hy, 0);
    fill(lx, 0);
    fill(t, 0);

    int cnt = 1;
    hy[p[0].ind] = cnt;
    lx[cnt] = p[0].x;
    rep(i, 1, p.size() - 1){
        if (p[i].x != p[i - 1].x){
            cnt += 1;
        }
        hy[p[i].ind] = cnt;
        lx[cnt] = p[i].x;
    }
    rep(i, 0, s.size() - 1){
        s[i].l = hy[s[i].l];
        s[i].r = hy[s[i].r];
    }
    build(1, 1, cnt);
    rep(i, 0, s.size() - 1){
        modify(1, s[i].l, s[i].r, s[i].v);
    }
//  printf("%d\n", len);
}
int main(void){
    int n;
    scanf("%d", &n);
    vector<int> u, d, l, r;
    rep(i, 1, n){
        int tu, td, tl, tr;
        scanf("%d%d%d%d", &tl, &td, &tr, &tu);
        l.pb(tl);
        d.pb(td);
        r.pb(tr);
        u.pb(tu);
    }
    solve(u, d, l, r);
    solve(r, l, d, u);
    printf("%d\n", len);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值