您的位置:首页 > 其它

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

2016-03-07 22:18 253 查看
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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: