preparing

map

用处

\(map\),映射,是一种提供一对一\(hash\)\(STL\),换句话说,可以把一种类型(任何类型都行,包括自定义的)映射到另一类型。

用法

调用

调用\(map\)要用到专门的头文件。

#include<map>

具体调用时,代码如下:\(map<\) 类型1,类型2 \(>\) 名称。

map<string,int> a;

用法

以上例为例,我们开了一个把字符串(\('string'\))映射到\(int\)\(map\)
使用时,比如我们要统计字符串出现的次数,读入字符串后,就可以使用如下代码统计次数。

string x;
scanf("%s",&x);
a[x]++;

换句话说,\(map\)可以让你使用除了\(int\)以外的类型为数组的下标,下面用例题讲解。

例题:CF651C Watchmen

题意

给定\(n\)个点,求有多少点之间的曼哈顿距离等于欧几里得距离。即有多少对点\((x_1,y_1),(x_2,y_2)\),满足\(|x1-x2|+|y1-y2|=\sqrt{(x_1-x_2)^2+(y_1-y_2)^2}\)

思路

曼哈顿距离等于欧几里得距离的两个点一定满足横坐标相同纵坐标相同。
根据这一点,我们可以推出本题的思路:逐个读入点,每次最终结果\(ans\)都应加上与此点横坐标相等的点的数目和纵坐标相等的点的数目。因为\(|xi|,|yi|\le10^9\),所以一定要开\(long long\)\(x\)\(y\),故该数组的下标应用\(long long\),所以\(map\)就可以上场了,就可以用和刚刚一样的方法统计\(x\)\(y\)坐标出现的次数。同时,因为有点会重复,所以结果要减去重复的点的个数,此时,我们呢就要统计重复点的个数,还是用\(map\),此时下标为点的坐标\((x,y)\),故要用\(make\)_\(pair(x,y)\)把它们结对作下标。

代码

#include<iostream>
#include<cstdio>
#include<map> 
#define maxn 200005
#define ll long long
using namespace std;
ll n,x,y;
map<ll,ll> mx;
map<ll,ll> my;
map<pair<ll,ll>,ll> point;
ll ans=0;
int main(){
	scanf("%d",&n);
	while(n--){
		scanf("%d%d",&x,&y);
		ans+=mx[x];
		ans+=my[y];
		ans-=point[make_pair(x,y)];
		mx[x]++;
		my[y]++;
		point[make_pair(x,y)]++;
	} 
	printf("%d",ans);
	return 0;
}
posted @ 2021-07-27 14:22  qzhwlzy  阅读(79)  评论(0)    收藏  举报