只有三个map的一篇题解
1. 手推公式
∣ x 2 − x 1 ∣ + ∣ y 2 − y 1 ∣ = ( x 2 − x 1 ) 2 + ( y 2 − y 1 ) 2 |x2-x1|+|y2-y1|=\sqrt{(x2-x1)^2+(y2-y1)^2} ∣x2−x1∣+∣y2−y1∣=(x2−x1)2+(y2−y1)2
设|x2-x1|=a,|y2-y1|=b
a + b = a 2 + b 2 a+b=\sqrt{a^2+b^2} a+b=a2+b2
( a + b ) 2 = a 2 + b 2 (a+b)^2=a^2+b^2 (a+b)2=a2+b2
a 2 + 2 a b + b 2 = a 2 + b 2 a^2+2ab+b^2=a^2+b^2 a2+2ab+b2=a2+b2
2 a b = 0 2ab=0 2ab=0
a b = 0 ab=0 ab=0
∣ x 2 − x 1 ∣ ∗ ∣ y 2 − y 1 ∣ = 0 |x2-x1|*|y2-y1|=0 ∣x2−x1∣∗∣y2−y1∣=0
∣ x 2 − x 1 ∣ = 0    o r    ∣ y 2 − y 1 ∣ = 0 |x2-x1|=0\:\:or\:\:|y2-y1|=0 ∣x2−x1∣=0or∣y2−y1∣=0
x 1 = x 2    o r    y 1 = y 2 x1=x2\:\:or\:\:y1=y2 x1=x2ory1=y2
2.算法
由公式可知,横纵坐标二选一相同时,两点符合要求
坐标值域很大,可以直接上map
X[]存某行出现过点数,Y[]存某列出现过的点数,p[][]存某个坐标出现过的点数
X[x]+Y[y]-p[x][y]就是答案
3.优化
众所周知,map复杂度是log级的,而unordered_map是O(1)的
所以对于两个下标是int的我们可以用unordered_map代替
4.补充
make_pair(x,y)的意思是将x,y搞成一个pair<,>型东西
以下两段代码等价:
a=make_pair(x,y);
a.first=x;
a.second=y;
(tips.因为CF的c++版本很高,所以要去掉斜杠那两句话,但NOIP中要加上)
#include <bits/stdc++.h>
//#include <tr1/unordered_map>
//using namespace std::tr1;
using namespace std;
unordered_map<int,int> X,Y;
map<pair<int,int>,int> p;
long long ans; //答案会爆int
int n;
signed main(){
scanf("%d",&n);
for(int i=1,x,y;i<=n;i++){
scanf("%d%d",&x,&y);
ans+=X[x]+Y[y]-p[make_pair(x,y)];
X[x]++;
Y[y]++;
p[make_pair(x,y)]++;
}
printf("%I64d",ans);
}