题意:坐标系中给出 n 个点,有两种计算距离的方法,一种是传统的两点间距离,另一种是横坐标差的绝对值加纵坐标差的绝对值。问 n 个点中这两种算法得到的答案一样的点对有多少个。(不算同一个点)
算出横坐标相等的点的个数存到 vector 里,再存纵坐标,然后遍历 vector 计算 Cn2。最后减去所有重复点的 Cn2。
#include<cstring>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
vector<int> num;
struct Point{
int x, y;
}P[200005];
long long cal(int x){
return (long long)x*(x-1)/2;
}
bool cmp1(Point a, Point b){
if(a.x != b.x) return a.x<b.x;
return a.y<b.y;
}
bool cmp2(Point a, Point b){
if(a.y != b.y) return a.y<b.y;
return a.x<b.x;
}
int main(){
//freopen("a.txt", "r", stdin);
int n;
P[0].x = 1e9+1;
P[0].y = 1e9+1;
while(~scanf("%d", &n)){
num.clear();
for(int i = 1; i <= n; i++){
scanf("%d %d", &P[i].x, &P[i].y);
}
sort(P+1, P+n+1, cmp1);
long long cnt = 1, ans = 0, flag = 1;
for(int i = 1; i <= n; i++){
if(P[i].x == P[i-1].x && P[i].y == P[i-1].y){
cnt++;
if(i == n){
ans += (long long)cnt*(cnt-1)/2;
cnt = 1;
}
}else if(cnt != 1){
ans += (long long)cnt*(cnt-1)/2;
cnt = 1;
}
if(P[i].x == P[i-1].x){
flag++;
if(i == n){
num.push_back(flag);
flag = 1;
}
}else if(flag != 1){
//cout << "test" << endl;
num.push_back(flag);
flag = 1;
}
}
sort(P+1, P+n+1, cmp2);
for(int i = 1; i <= n; i++){
if(P[i].y == P[i-1].y){
flag++;
if(i == n){
num.push_back(flag);
flag = 1;
}
}else if(flag != 1){
num.push_back(flag);
flag = 1;
}
}
long long ans1 = 0;
for(int i = 0; i < num.size(); i++){
//cout << num[i] <<endl;
ans1 += cal(num[i]);
}
ans1 -= ans;
//break;
//cout << ans << endl;
cout << ans1 << endl;
}
return 0;
}