题目描述
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
and v_1 < v_2v
1
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
and v_1 < v_2v
1
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;
}