zoukankan      html  css  js  c++  java
  • 扫描线模版

    求解矩形面积交:

    https://www.luogu.com.cn/problem/P5490

    为了和区间匹配: 线段树的[l,r] 实际上代表了区间 [l,r + 1]

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    
    #define ll long long
    #define ull unsigned long long
    #define ls nod<<1
    #define rs (nod<<1)+1
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define INF 0x3f3f3f3f
    #define max(a, b) (a>b?a:b)
    #define min(a, b) (a<b?a:b)
    
    
    const double eps = 1e-8;
    const int maxn = 1e6 + 10;
    const ll MOD = 1e9 + 7;
    const int mlog=20;
    
    int sgn(double a) { return a < -eps ? -1 : a < eps ? 0 : 1; }
    
    using namespace std;
    
    ll x1,y1,x2,y2,X[maxn << 1];
    
    struct ScanLine {
        ll l,r,h;
        int mark;
    
        bool operator < (const ScanLine &rhs) const {
            return h < rhs.h;
        }
    } line[maxn << 2];
    
    struct segment_tree {
        int l,r,sum;
        ll len;
    }tree[maxn << 2];
    
    void build(int l,int r,int nod) {
        tree[nod].l = l,tree[nod].r = r;
        tree[nod].len = 0;
        tree[nod].sum = 0;
        if (l == r)
            return ;
        int mid = (l + r) >> 1;
        build(l,mid,ls);
        build(mid+1,r,rs);
    }
    
    void push_up(int nod) {
        int l = tree[nod].l,r = tree[nod].r;
        if (tree[nod].sum) {
            tree[nod].len = X[r+1] - X[l];
        }
        else
            tree[nod].len = tree[ls].len + tree[rs].len;
    }
    
    void modify(ll x,ll y,int f,int nod) {
        int l = tree[nod].l,r = tree[nod].r;
        if (X[r+1] <= x || X[l] >= y)
            return ;
        if (X[l] >= x && X[r+1] <= y) {
            tree[nod].sum += f;
            push_up(nod);
            return ;
        }
        modify(x,y,f,ls);
        modify(x,y,f,rs);
        push_up(nod);
    }
    
    int main() {
        int n;
        scanf("%d",&n);
        for (int i = 1;i <= n;i++) {
            scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
            X[2 * i - 1] = x1,X[2 * i] = x2;
            line[2 * i - 1] = (ScanLine){x1,x2,y1,1};
            line[2 * i] = (ScanLine){x1,x2,y2,-1};
        }
        n <<= 1;
        sort(line + 1,line + 1 + n);
        sort(X + 1,X + 1 + n);
        int tot = unique(X + 1,X + n + 1) - X - 1;
        build(1,tot-1,1);
        ll ans = 0;
        for (int i = 1;i < n;i++) {
            modify(line[i].l,line[i].r,line[i].mark,1);
            ans += tree[1].len * (line[i+1].h - line[i].h);
        }
        printf("%lld
    ",ans);
        return 0;
    }

    求矩形的周长:

    https://www.luogu.com.cn/problem/P1856

     

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    
    #define ll long long
    #define ull unsigned long long
    #define ls nod<<1
    #define rs (nod<<1)+1
    #define pii pair<int,int>
    #define mp make_pair
    #define pb push_back
    #define INF 0x3f3f3f3f
    #define max(a, b) (a>b?a:b)
    #define min(a, b) (a<b?a:b)
    
    
    const double eps = 1e-8;
    const int maxn = 1e6 + 10;
    const ll MOD = 1e9 + 7;
    const int mlog=20;
    
    int sgn(double a) { return a < -eps ? -1 : a < eps ? 0 : 1; }
    
    using namespace std;
    
    ll x1,y1,x2,y2,X[maxn << 1];
    
    struct ScanLine {
        ll l,r,h;
        int mark;
    
        // 这里和面积交那里多了一个特判
        bool operator < (const ScanLine &rhs) const {
           if (h == rhs.h)
               return mark > rhs.mark;
           return h < rhs.h;
        }
    } line[maxn << 2];
    
    struct segment_tree {
        int l,r,sum,c;
        bool lc,rc;
        ll len;
    }tree[maxn << 2];
    
    void build(int l,int r,int nod) {
        tree[nod].l = l,tree[nod].r = r;
        tree[nod].lc = tree[nod].rc = false;
        tree[nod].len = 0;
        tree[nod].sum = 0;
        if (l == r)
            return ;
        int mid = (l + r) >> 1;
        build(l,mid,ls);
        build(mid+1,r,rs);
    }
    
    void push_up(int nod) {
        int l = tree[nod].l,r = tree[nod].r;
        if (tree[nod].sum) {
            tree[nod].len = X[r+1] - X[l];
            tree[nod].lc = tree[nod].rc = true;
            tree[nod].c = 1;
        }
        else {
            tree[nod].len = tree[ls].len + tree[rs].len;
            tree[nod].lc = tree[ls].lc,tree[nod].rc = tree[rs].rc;
            tree[nod].c = tree[ls].c + tree[rs].c;
            if (tree[ls].rc && tree[rs].lc)
                tree[nod].c -= 1;
        }
    }
    
    void modify(ll x,ll y,int f,int nod) {
        int l = tree[nod].l,r = tree[nod].r;
        if (X[r+1] <= x || X[l] >= y)
            return ;
        if (X[l] >= x && X[r+1] <= y) {
            tree[nod].sum += f;
            push_up(nod);
            return ;
        }
        modify(x,y,f,ls);
        modify(x,y,f,rs);
        push_up(nod);
    }
    
    int main() {
        int n;
        scanf("%d",&n);
        for (int i = 1;i <= n;i++) {
            scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
            X[2 * i - 1] = x1,X[2 * i] = x2;
            line[2 * i - 1] = (ScanLine){x1,x2,y1,1};
            line[2 * i] = (ScanLine){x1,x2,y2,-1};
        }
        n <<= 1;
        sort(line + 1,line + 1 + n);
        sort(X + 1,X + 1 + n);
        int tot = unique(X + 1,X + n + 1) - X - 1;
        build(1,tot-1,1);
        ll ans = 0;
        ll pre = 0;
        for (int i = 1;i < n;i++) {
            modify(line[i].l,line[i].r,line[i].mark,1);
            ans += abs(pre - tree[1].len);
            pre = tree[1].len;
            ans += 2 * tree[1].c * (line[i + 1].h - line[i].h);
        }
        ans += line[n].r - line[n].l;
        printf("%lld
    ",ans);
        return 0;
    }

    具体的讲解的博客:https://ncc79601.blog.luogu.org/scan-line

  • 相关阅读:
    IntelliJ IDEA 14.03 java 中文文本处理中的编码格式设置
    应聘感悟
    STL string分析
    CUDA SDK VolumeRender 分析 (1)
    BSP
    CUDA SDK VolumeRender 分析 (3)
    CUDA SDK VolumeRender 分析 (2)
    Windows软件发布时遇到的一些问题
    Ten Commandments of Egoless Programming (转载)
    复习下光照知识
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/13398603.html
Copyright © 2011-2022 走看看