Codeforces #345 Div2 C Watchmen 容斥

来源:互联网 发布:java是什么意思啊 编辑:程序博客网 时间:2024/04/29 16:16

给你n个点的坐标(x,y)。求哈密顿距离和欧几里德距离相同的点对有多少,所给的点可能是重合的。

哈密顿距离:|xi-xj|+|yi-yj|,欧几里德距离:根号下((xi-xj)^2+(yi-yj)^2)。把两边平方一下,再一消去,就可发现,只有当(xi-xj)和(yi-yj)至少有一个为0时,两种距离才相等,就是两个点的横纵坐标至少有一个是一样的。

所以,因为有重点,就显得有点麻烦,但其实想了想,也不麻烦啊。首先把所有点按x坐标排序,每类所有x坐标相同的点,加入有m个,取C(m,2)。不管纵坐标相不相同,都可以这么取。然后再按y坐标排序,同样对每类所有y坐标相同的点,取个C(m,2)。这时就会发现,那些两两相同的,被计算了两次。所以找到每类x和y都相同的点,也取C(m,2)。把最后这个减去就好了。

代码:

#include <set>#include <map>#include <queue>#include <stack>#include <cmath>#include <string>#include <vector>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define maxn 200002struct node{int x, y;}a[maxn];bool cmp1(node a, node b){if (a.x < b.x)return 1;else if (a.x == b.x&&a.y < b.y)return 1;elsereturn 0;}bool cmp2(node a, node b){if (a.y < b.y)return 1;else if (a.y == b.y&&a.x < b.x)return 1;elsereturn 0;}int main(){//freopen("input.txt", "r", stdin);int n;long long cnt = 0, ans = 0, l = 0;scanf("%d", &n);for (int i = 0; i < n; ++i)scanf("%d%d", &a[i].x, &a[i].y);sort(a, a + n, cmp1);cnt = 1;for (int i = 1; i < n; ++i){if (a[i].x == a[i - 1].x)cnt++;else{ans += cnt*(cnt - 1) / 2;cnt = 1;}}ans += cnt*(cnt - 1) / 2;cnt = 1;sort(a, a + n, cmp2);for (int i = 1; i < n; ++i){if (a[i].y == a[i - 1].y)cnt++;else{ans += cnt*(cnt - 1) / 2;cnt = 1;}}ans += cnt*(cnt - 1) / 2;cnt = 1;for (int i = 1; i < n; ++i){if (a[i].y == a[i - 1].y&&a[i].x == a[i - 1].x)cnt++;else{ans -= cnt*(cnt - 1) / 2;cnt = 1;}}ans -= cnt*(cnt - 1) / 2;cnt = 1;printf("%I64d\n", ans);//while (1);//system("pause");return 0;}

0 0