CodeForces650AWatchmen

来源:互联网 发布:知乎 美国大选 编辑:程序博客网 时间:2024/06/05 23:43

Description

Watchmen are in a danger and Doctor Manhattan together with his friend Daniel Dreiberg should warn them as soon as possible. There are n watchmen on a plane, the i-th watchman is located at point (xi, yi).

They need to arrange a plan, but there are some difficulties on their way. As you know, Doctor Manhattan considers the distance between watchmen i and j to be |xi - xj| + |yi - yj|. Daniel, as an ordinary person, calculates the distance using the formula .

The success of the operation relies on the number of pairs (i, j) (1 ≤ i < j ≤ n), such that the distance between watchman i and watchmen j calculated by Doctor Manhattan is equal to the distance between them calculated by Daniel. You were asked to compute the number of such pairs.

Input

The first line of the input contains the single integer n (1 ≤ n ≤ 200 000) — the number of watchmen.

Each of the following n lines contains two integers xi and yi (|xi|, |yi| ≤ 109).

Some positions may coincide.

Output

Print the number of pairs of watchmen such that the distance between them calculated by Doctor Manhattan is equal to the distance calculated by Daniel.

Sample Input

Input
31 17 51 5
Output
2
Input
60 00 10 2-1 10 11 1
Output
11

Hint

In the first sample, the distance between watchman 1 and watchman 2 is equal to |1 - 7| + |1 - 5| = 10 for Doctor Manhattan and  for Daniel. For pairs (1, 1)(1, 5) and (7, 5)(1, 5) Doctor Manhattan and Daniel will calculate the same distances.

代码:
#include<stdio.h>#include<iostream>#include<algorithm>using namespace std;struct st{long long x;long long  y;}a[200001];bool cmp(st q,st w){return q.x<w.x; }  bool cmo(st q,st w) { return q.y<w.y; } bool cmi(st q,st w) { if(q.x==w.x) return q.y<w.y; return q.x<w.x; }int main(){ long long  n; while(scanf("%lld",&n)!=EOF) { long long  i,j,sum=1,ans=0; for(i=0;i<n;i++) { scanf("%lld %lld",&a[i].x,&a[i].y); } sort(a,a+n,cmp); for(i=1;i<n;i++) { if(a[i].x==a[i-1].x) sum++; else { ans=ans+sum*(sum-1)/2; sum=1; } } ans=ans+sum*(sum-1)/2; sum=1; sort(a,a+n,cmo); for(i=1;i<n;i++) { if(a[i].y==a[i-1].y) { sum++; } else { ans=ans+sum*(sum-1)/2; sum=1; } } ans=ans+sum*(sum-1)/2; sum=1; sort(a,a+n,cmi); for(i=1;i<n;i++) { if(a[i].y==a[i-1].y&&a[i].x==a[i-1].x) { sum++; } else { ans-=sum*(sum-1)/2; sum=1; } } ans-=sum*(sum-1)/2; printf("%lld\n",ans); }return  0;}
题意:给你一些点,让你判断分别用两种公式计算两点之间距离结果一样的有多少个。
思路:直接用题意所给的公式肯定会超时的啦!(然而傻傻的我开始时还是直接用了)!将两个公式列出来会发现当x1=x2,或者y1=y2时计算结果就会一样。如果这时你就傻傻得以为直接一个冒泡判断就ac的话还是太年轻,会超时的。(我还是犯这个错了!)所以要想如何简化判断过程。这世界就要用到快排了,先对x坐标快排判断有多少个点x坐标一样,再用公式x*(x-1)/2得到x坐标一样得点相同有多少个。同理y也是这样。不过这样做会有重复的,那就是x和y都一样的点会多计算。这时在快排一次
 bool cmi(st q,st w) { if(q.x==w.x) return q.y<w.y; return q.x<w.x; }
判断xy都一样的再减去就得到最后结果了。
0 0
原创粉丝点击