zoukankan      html  css  js  c++  java
  • Codeforces

    https://codeforc.es/contest/1194/problem/E

    给5000条正常的(同方向不会重叠,也不会退化成点的)线段,他们都是平行坐标轴方向的,求能组成多少个矩形。

    先进行坐标偏移,按水平线和垂直线分好类。

    用扫描线的思路,从底部的水平线开始往上扫,先标记所有与该条水平线相交的竖直线,加入队列,给竖直线按y排序。

    先把结束的竖直线undo掉,然后从这条水平线A的下一条水平线B开始,询问B线覆盖的区间中还有多少标记的竖直线。

    注意要么偏移5001,要么把区间查询这里加个特判。防止越界到-1。

    慢一点点的代码。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MAXN = 10001;
    int bit[MAXN + 5];
    
    inline int prefix_sum(int x) {
        int res = 0;
        for(; x; x -= x & -x)
            res += bit[x];
        return res;
    }
    
    inline void add(int x, int v) {
        for(; x <= MAXN; x += x & -x)
            bit[x] += v;
    }
    
    inline int range_sum(int l, int r) {
        return prefix_sum(r) - prefix_sum(l - 1);
    }
    
    struct Vertical_Line {
        int x, y1, y2;
        bool operator<(const Vertical_Line& vl) {
            return x != vl.x ? x < vl.x : y1 < vl.y1;
        }
    } vl[5005];
    int  vtop;
    
    struct Vertical_Line_End {
        int x, y;
        bool operator<(const Vertical_Line_End& vle) {
            return y < vle.y;
        }
    } vle[5005];
    int vle_back, vle_front;
    
    struct Horizontal_Line {
        int x1, x2, y;
        bool operator<(const Horizontal_Line& hl) {
            return y != hl.y ? y < hl.y : x1 < hl.x1;
        }
    } hl[5005];
    int htop;
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
        //freopen("Yinku.out", "w", stdout);
    #endif // Yinku
        int n;
        while(~scanf("%d", &n)) {
            vtop = 0, htop = 0;
            int x1, y1, x2, y2;
            for(int i = 1; i <= n; i++) {
                scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
                x1 += 5001, y1 += 5001, x2 += 5001, y2 += 5001;
                if(x1 > x2)
                    swap(x1, x2);
                if(y1 > y2)
                    swap(y1, y2);
                if(x1 == x2) {
                    ++vtop;
                    vl[vtop].x = x1;
                    vl[vtop].y1 = y1;
                    vl[vtop].y2 = y2;
                } else {
                    ++htop;
                    hl[htop].y = y1;
                    hl[htop].x1 = x1;
                    hl[htop].x2 = x2;
                }
            }
            sort(vl + 1, vl + 1 + vtop);
            sort(hl + 1, hl + 1 + htop);
            ll ans = 0;
            for(int hi = 1; hi <= htop; hi++) {
                vle_front = 1;
                vle_back = 0;
                for(int vi = 1; vi <= vtop; vi++) {
                    if(vl[vi].x >= hl[hi].x1 && vl[vi].x <= hl[hi].x2 && vl[vi].y1 <= hl[hi].y && vl[vi].y2 >= hl[hi].y) {
                        add(vl[vi].x, 1);
                        ++vle_back;
                        vle[vle_back].x = vl[vi].x;
                        vle[vle_back].y = vl[vi].y2;
                    }
                }
                sort(vle + 1, vle + 1 + vle_back);
                int cury = hl[hi].y;
                for(int hii = hi + 1; hii <= htop; hii++) {
                    while(vle_front <= vle_back && vle[vle_front].y < hl[hii].y) {
                        add(vle[vle_front].x, -1);
                        vle_front++;
                    }
                    int tmp = range_sum(hl[hii].x1, hl[hii].x2);
                    ans += (tmp * (tmp - 1) >> 1);
                }
                while(vle_front <= vle_back) {
                    add(vle[vle_front].x, -1);
                    vle_front++;
                }
            }
            printf("%lld
    ", ans);
        }
    }
    

    其实一开始把竖直线也按y排序就省掉了后面的排序了的。快了一点点。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int MAXN = 10001;
    int bit[MAXN + 5];
    
    inline int prefix_sum(int x) {
        int res = 0;
        for(; x; x -= x & -x)
            res += bit[x];
        return res;
    }
    
    inline void add(int x, int v) {
        for(; x <= MAXN; x += x & -x)
            bit[x] += v;
    }
    
    inline int range_sum(int l, int r) {
        return prefix_sum(r) - prefix_sum(l - 1);
    }
    
    struct Vertical_Line {
        int x, y1, y2;
        bool operator<(const Vertical_Line& vl) {
            return y2 < vl.y2;
        }
    } vl[5005];
    int  vtop;
    
    struct Vertical_Line_End {
        int x, y;
    } vle[5005];
    int vle_back, vle_front;
    
    struct Horizontal_Line {
        int x1, x2, y;
        bool operator<(const Horizontal_Line& hl) {
            return y != hl.y ? y < hl.y : x1 < hl.x1;
        }
    } hl[5005];
    int htop;
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
        //freopen("Yinku.out", "w", stdout);
    #endif // Yinku
        int n;
        while(~scanf("%d", &n)) {
            vtop = 0, htop = 0;
            int x1, y1, x2, y2;
            for(int i = 1; i <= n; i++) {
                scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
                x1 += 5001, y1 += 5001, x2 += 5001, y2 += 5001;
                if(x1 > x2)
                    swap(x1, x2);
                if(y1 > y2)
                    swap(y1, y2);
                if(x1 == x2) {
                    ++vtop;
                    vl[vtop].x = x1;
                    vl[vtop].y1 = y1;
                    vl[vtop].y2 = y2;
                } else {
                    ++htop;
                    hl[htop].y = y1;
                    hl[htop].x1 = x1;
                    hl[htop].x2 = x2;
                }
            }
            sort(vl + 1, vl + 1 + vtop);
            sort(hl + 1, hl + 1 + htop);
            ll ans = 0;
            for(int hi = 1; hi <= htop; hi++) {
                vle_front = 1;
                vle_back = 0;
                for(int vi = 1; vi <= vtop; vi++) {
                    if(vl[vi].x >= hl[hi].x1 && vl[vi].x <= hl[hi].x2 && vl[vi].y1 <= hl[hi].y && vl[vi].y2 >= hl[hi].y) {
                        add(vl[vi].x, 1);
                        ++vle_back;
                        vle[vle_back].x = vl[vi].x;
                        vle[vle_back].y = vl[vi].y2;
                    }
                }
                //sort(vle + 1, vle + 1 + vle_back);
                int cury = hl[hi].y;
                for(int hii = hi + 1; hii <= htop; hii++) {
                    while(vle_front <= vle_back && vle[vle_front].y < hl[hii].y) {
                        add(vle[vle_front].x, -1);
                        vle_front++;
                    }
                    int tmp = range_sum(hl[hii].x1, hl[hii].x2);
                    ans += (tmp * (tmp - 1) >> 1);
                }
                while(vle_front <= vle_back) {
                    add(vle[vle_front].x, -1);
                    vle_front++;
                }
            }
            printf("%lld
    ", ans);
        }
    }
    
  • 相关阅读:
    MySql 获取当前节点及递归所有上级节点
    MySql创建树结构递归查询存储过程
    F2工作流引擎Web层全新扁平化UI上线
    F2工作流引擎参与者类型成员的交、并、互拆计算规则
    F2工作流引擎之组织用户模型(四)
    F2工作流引擎之 工作流运转模型(三)
    F2工作流引擎之 概述(一)
    离线安装docker,并导入docker镜像
    sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set 的解决办法
    yml 文件中使用环境变量
  • 原文地址:https://www.cnblogs.com/Yinku/p/11195977.html
Copyright © 2011-2022 走看看