[POJ1117] Picture && 线段树+扫描线

来源:互联网 发布:格罗兹尼巷战 知乎 编辑:程序博客网 时间:2024/05/22 02:28

把边排序 从左往右进行扫描计算周长 注意排序时左边的边要排在右边的边的前面

#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>#define SF scanf#define PF printf#define ls (i*2)#define rs (i*2+1)using namespace std;const int MAXN = 5000;struct Line {    int x, y1, y2;    bool GetIn;    Line () {}    Line(int _x, int _y, int __y, bool ok) : x(_x), y1(_y), y2(__y), GetIn(ok) {}    bool operator < (const Line &t) const {        return (x < t.x || (( x == t.x) && (GetIn && !t.GetIn)));    }};Line L[MAXN*2+10];int y[MAXN*2+10];struct Node {    int l, r, cnt, Seg, sum;    bool L_ok, R_ok;};struct Seg_Tree {    Node tree[MAXN * 4 + 10];    void build(int i, int l, int r) {        int mid = (l + r) >> 1;        tree[i].l = l; tree[i].r = r;        tree[i].Seg = tree[i].cnt = tree[i].sum = 0;        tree[i].L_ok = tree[i].R_ok = false;        if(l == r-1) return ;        build(ls, l, mid);        build(rs, mid, r);    }    void update(int i) {        if(tree[i].cnt) {            tree[i].L_ok = tree[i].R_ok = true;            tree[i].Seg = 1;            tree[i].sum = y[tree[i].r] - y[tree[i].l];        }        else {            if(tree[i].l == tree[i].r - 1) {                tree[i].L_ok = tree[i].R_ok = false;                tree[i].Seg = 0;                tree[i].sum = 0;            }            else {                tree[i].L_ok = tree[ls].L_ok;                tree[i].R_ok = tree[rs].R_ok;                tree[i].Seg = tree[ls].Seg + tree[rs].Seg;                if(tree[ls].R_ok && tree[rs].L_ok) tree[i].Seg--;                tree[i].sum = tree[ls].sum + tree[rs].sum;            }        }    }    void insert(int i, int l, int r, bool f) {        if(r < tree[i].l || tree[i].r <= l) return ;        if(l <= tree[i].l && tree[i].r <= r) {            tree[i].cnt += (f ? 1 : -1);            update(i);            return ;        }        insert(ls, l, r, f);        insert(rs, l, r, f);        update(i);    }} seg;int main(){    int n;    while(~SF("%d", &n)) {        for(int i = 1; i <= n; i++) {            int x1, x2, y1, y2;            SF("%d%d%d%d", &x1, &y1, &x2, &y2);            y[i*2-1] = y1; y[i*2] = y2;            L[i*2-1] = Line(x1, y1, y2, true);            L[i*2] = Line(x2, y1, y2, false);        }        sort(y+1, y+1+2*n);        sort(L+1, L+1+2*n);        int N = unique(y+1, y+1+2*n) - (y+1);        seg.build(1, 1, N);        int Len = 0, ans = 0;        for(int i = 1; i <= 2*n; i++) {            int pos1 = lower_bound(y+1, y+1+N, L[i].y1) - y;            int pos2 = lower_bound(y+1, y+1+N, L[i].y2) - y;            seg.insert(1, pos1, pos2, L[i].GetIn);            ans += abs(Len - seg.tree[1].sum);            ans += seg.tree[1].Seg * 2 * (L[i+1].x - L[i].x);            Len = seg.tree[1].sum;        }        printf("%d\n" , ans);    }}


0 0
原创粉丝点击