【CF1194E】 Count The Rectangles

题目

题目描述
There are nn segments drawn on a plane; the ii -th segment connects two points ( x_{i, 1}x
i,1

, y_{i, 1}y
i,1

) and ( x_{i, 2}x
i,2

, y_{i, 2}y
i,2

). Each segment is non-degenerate, and is either horizontal or vertical — formally, for every i \in [1, n]i∈[1,n] either x_{i, 1} = x_{i, 2}x
i,1

=x
i,2

or y_{i, 1} = y_{i, 2}y
i,1

=y
i,2

(but only one of these conditions holds). Only segments of different types may intersect: no pair of horizontal segments shares any common points, and no pair of vertical segments shares any common points.

We say that four segments having indices h_1h
1

, h_2h
2

, v_1v
1

and v_2v
2

such that h_1 < h_2h
1

2

and v_1 < v_2v
1

2

form a rectangle if the following conditions hold:

segments h_1h
1

and h_2h
2

are horizontal;
segments v_1v
1

and v_2v
2

are vertical;
segment h_1h
1

intersects with segment v_1v
1

;
segment h_2h
2

intersects with segment v_1v
1

;
segment h_1h
1

intersects with segment v_2v
2

;
segment h_2h
2

intersects with segment v_2v
2

.
Please calculate the number of ways to choose four segments so they form a rectangle. Note that the conditions h_1 < h_2h
1

2

and v_1 < v_2v
1

2

should hold.

输入格式
The first line contains one integer nn ( 1 \le n \le 50001≤n≤5000 ) — the number of segments.

Then nn lines follow. The ii -th line contains four integers x_{i, 1}x
i,1

, y_{i, 1}y
i,1

, x_{i, 2}x
i,2

and y_{i, 2}y
i,2

denoting the endpoints of the ii -th segment. All coordinates of the endpoints are in the range [-5000, 5000][−5000,5000] .

It is guaranteed that each segment is non-degenerate and is either horizontal or vertical. Furthermore, if two segments share a common point, one of these segments is horizontal, and another one is vertical.

输出格式
Print one integer — the number of ways to choose four segments so they form a rectangle.

题意翻译
二维坐标系上有 nn 条线段,每条线段连接 (x_{i,1},y_{i,1}),(x_{i,2},y_{i,2})(x
i,1

,y
i,1

),(x
i,2

,y
i,2

) 两个整点,且所有线段平行于坐标轴,保证平行于同一条坐标轴的线段不相交。求这些线段能组成多少个矩形。

(1 \leq n \leq 5 \times 10^3,x,y \in [-5 \times 10^3,5 \times 10^3])(1≤n≤5×10
3
,x,y∈[−5×10
3
,5×10
3
])

输入输出样例
输入 #1复制
7
-1 4 -1 -2
6 -1 -2 -1
-2 3 6 3
2 -2 2 4
4 -1 4 3
5 3 5 1
5 2 1 2
输出 #1复制
7
输入 #2复制
5
1 5 1 0
0 1 5 1
5 4 0 4
4 2 4 0
4 3 4 5
输出 #2复制
0
说明/提示
The following pictures represent sample cases:

思路

先把横线和竖线分开存储,我们可以n2预处理出与第 i 条横线相交的竖线集合为 fi
接下来枚举矩形的上下两条边为第 i 条横线和第 j 条横线,那么同时与这两条横线相交的竖线集合为fi∩fj
假设这个集合的大小为 x,则能形成C(x,2)个矩形,累加就能得到答案。
bitset优化即可

代码

#include
using namespace std;
int main() {
    read(n);
    for (int x1, y1, x2, y2, i = 1; i <= n; ++i) {
        read(x1), read(y1), read(x2), read(y2);
        if (x1 > x2) swap(x1, x2);
        if (y1 > y2) swap(y1, y2);
        if (y1 == y2) row[++cnt1] = (Node) { x1, y1, x2, y2 };
        else col[++cnt2] = (Node) { x1, y1, x2, y2 };
    }
    if (cnt1 < cnt2) {
        for (int i = 1; i <= cnt1; ++i)
            for (int j = 1; j <= cnt2; ++j)
                if (row[i].x1 <= col[j].x1 && row[i].x2 >= col[j].x1 && 
                col[j].y1 <= row[i].y1 && col[j].y2 >= row[i].y2)
                    f[i][j] = 1;
        for (int i = 1; i <= cnt1; ++i)
            for (int j = i + 1; j <= cnt1; ++j) {
                int t = (f[i] & f[j]).count();
                ans += 1ll * t * (t - 1) >> 1;
            }
    } else {
        for (int i = 1; i <= cnt1; ++i)
            for (int j = 1; j <= cnt2; ++j)
                if (row[i].x1 <= col[j].x1 && row[i].x2 >= col[j].x1 && 
                col[j].y1 <= row[i].y1 && col[j].y2 >= row[i].y2)
                    f[j][i] = 1;
        for (int i = 1; i <= cnt2; ++i)
            for (int j = i + 1; j <= cnt2; ++j) {
                int t = (f[i] & f[j]).count();
                ans += 1ll * t * (t - 1) >> 1;
            }
    }
    write(ans);
    putchar('\n'); 
    return 0;
}

你可能感兴趣的:(【CF1194E】 Count The Rectangles)