您的位置:首页 > 运维架构

【bzoj1604】【Usaco2008 Open】Cow Neighborhoods (set+曼哈顿距离性质+并查集)奶牛的邻居

2016-05-17 09:43 169 查看
题目链接:

http://www.lydsy.com/JudgeOnline/problem.php?id=1604

题解:

首先要做这道题我们知道曼哈顿距离的一个性质,那就是:

如果原来坐标是(x, y),令新的坐标为(X, Y), 其中X = x + y, Y = x - y

曼哈顿距离 = |x1 - x2| + |y1 - y2| = max ( |X1 - X2|, |Y1 - Y2| );

还有就是如何运用set,这个百度里可以搜到,看这个东西大概可以知道set怎么用

http://baike.baidu.com/link?url=uVFabYTc3qYwwhKfxKuS-vfAFSKYQquK8iEq4vVrRXyFDm8Ps9oH_GADc6Lfs40cTLfbjfXhnMVLRL-NtnnN4q

接下来就是这道题的关键点,如何判断哪些点在同一个块中:

首先我们将给出的每个点的坐标用(x+y , x-y)来表示,这样的话按新的x坐标从小到大排序,维护一个队列满足队首到队尾的X坐标(X=x+y)距离小于c,这样的话 max ( |X1 - X2|, |Y1 - Y2| ) 中 |X1 - X2| 就满足小于c了,如何满足 |Y1 - Y2| 也小于c呢,我们需要用到平衡树即set,如果新加入元素在set中的前驱后继与它的Y值差值不超过c,则用并查集将他们连在一起,set本身有好多用法,可以参照上面给出的网页。

代码:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<set>
using namespace std;
typedef long long ll;
const ll inf=1e16;
struct node{
ll x;ll y;int id;
}a[100005];
int c,n,fa[100005],cnt[100005];
multiset<node>s;
node jia(ll xx,ll yy,int idd)
{
node tmp;
tmp.x=xx;tmp.y=yy;tmp.id=idd;
return tmp;
}
int cmp(node x,node y)
{
if (x.x!=y.x)
return x.x<y.x;
return x.y<y.y;
}
bool operator < (const node a, const node b)
{
return a.y < b.y;
}
int find(int x)
{
if (fa[x]==x)return x;
return fa[x]=find(fa[x]);
}
int num;
void unio(int x,int y)
{
//cout<<x<<' '<<y<<endl;
int X=find(x);
int Y=find(y);
if (X!=Y)
{
fa[X]=Y;
num--;
}
}
int main()
{
scanf("%d%d",&n,&c);num=n;
for (int i=1;i<=n;i++)
{
ll x,y;
fa[i]=i;
scanf("%lld%lld",&x,&y);
a[i].x=x+y;a[i].y=x-y;
a[i].id=i;
}
sort(a+1,a+1+n,cmp);
s.insert(jia(0,inf,0));
s.insert(jia(0,-inf,0));
s.insert(a[1]);
int head=1;
node l,r;
for (int i=2;i<=n;i++)
{
while(a[i].x-a[head].x>c)
{
s.erase(s.find(a[head]));
head++;
}
set <node> ::iterator it=s.lower_bound(a[i]);
r=*it;it--;l=*it;
if (a[i].y-l.y<=c)
unio(a[i].id,l.id);
if (r.y-a[i].y<=c)
unio(a[i].id,r.id);
s.insert(a[i]);
}
int sum=-1;
for (int i=1;i<=n;i++)
{
int tmp=find(i);
cnt[tmp]++;
sum=max(sum,cnt[tmp]);
}
printf("%d %d\n",num,sum);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: