cf#345-C - Watchmen-map离散化

本文介绍了一种在给定点集上计算特定距离点对数量的方法,通过点的离散化处理和排序策略来解决大范围坐标下的计算难题。文章详细解释了算法思路,并提供了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://codeforces.com/contest/651/problem/C


给你n个点,要求有多少对点满足   |xi - xj| + |yi - yj|.=.

也就是 这两个点 在平行于x或y轴的直线上


x,y的范围太大 1e9,但是n只有2e5

我们把点离散化后,看遍历所有与X轴平行的直线(当然就是只看出现过的x值),看上面有多少个点,如果有X个点,显然 X方向的这些点对答案的贡献就是 (x-1)*x/2

y轴同理


要注意的是,会有重合的点,重合的点 在X或Y方向 的贡献会被计算了两次


只需要把所有点排个序,找出重合点的个数,对于重合的A点X个,只需要减去一次贡献即可,也就是x*(x-1)/2


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;

const double pi=acos(-1.0);
double eps=0.000001;
  
map<__int64 ,__int64 > ::iterator it;
map<__int64 ,__int64 > sbx,sby;
struct node
{
	__int64 x,y;
};
bool cmp(node a,node b)
{
	if (a.x!=b.x)
	return a.x<b.x;
	return a.y<b.y;
}
node tm[200005];
int main()
{
	
	  int n;
	  cin>>n;
	  __int64 i;
	  for (i=1;i<=n;i++)
	  {
		  scanf("%I64d%I64d",&tm[i].x,&tm[i].y);
		  sbx[tm[i].x]++;
		  sby[tm[i].y]++;
	  }
	  sort(tm+1,tm+1+n,cmp);
	 
	
	  __int64 ans=0;
	for (it=sbx.begin();it!=sbx.end();it++)
	{
		__int64 tmp=it->second;
		ans+=tmp*(tmp-1)/2;
	}
	for (it=sby.begin();it!=sby.end();it++)
	{
		__int64 tmp=it->second;
		ans+=tmp*(tmp-1)/2;
	}
	__int64 ret=0;
	    for (i=1;i<=n;i++)
	  {
		  int j=i+1;
		 while (tm[i].x==tm[j].x&&tm[i].y==tm[j].y&&j<=n)
			  j++;
		  ret=j-i;
		 ans-=ret*(ret-1)/2;
		 i=j-1;
	  }
	printf("%I64d\n",ans);
	
	
	
	
	
	
	return 0;
	
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值