CF650A Watchmen(STL+map)


CF650A Watchmen


只有三个map的一篇题解


1. 手推公式

\(|x2-x1|+|y2-y1|=\sqrt{(x2-x1)^2+(y2-y1)^2}\)

设|x2-x1|=a,|y2-y1|=b

\(a+b=\sqrt{a^2+b^2}\)

\((a+b)^2=a^2+b^2\)

\(a^2+2ab+b^2=a^2+b^2\)

\(2ab=0\)

\(ab=0\)

\(|x2-x1|*|y2-y1|=0\)

\(|x2-x1|=0\:\:or\:\:|y2-y1|=0\)

\(x1=x2\:\:or\:\:y1=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);
}

posted @ 2019-07-27 19:22  think_twice  阅读(251)  评论(0编辑  收藏  举报