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);
        }
    }
    
  • 相关阅读:
    3.Appium运行时出现:Original error: Android devices must be of API level 17 or higher. Please change your device to Selendroid or upgrade Android on your device
    3.Python连接数据库PyMySQL
    2.Python输入pip命令出现Unknown or unsupported command 'install'问题解决
    2.Linux下安装Jenkins
    5.JMeter测试mysql数据库
    Android 4学习(7):用户界面
    Android 4学习(6):概述
    Android 4学习(5):概述
    Android 4学习(4):概述
    Android 4学习(3):概述
  • 原文地址:https://www.cnblogs.com/Yinku/p/11195977.html
Copyright © 2011-2022 走看看