【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本身有好多用法,可以参照上面给出的网页。
代码:
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); }
相关文章推荐
- 【bzoj 1604】: [Usaco2008 Open]Cow Neighborhoods 奶牛的邻居 set+并查集
- hadoop、hbase、hive、zookeeper版本对应关系
- Linux 下如何安装软件?
- EmguCV学习 与opencv的区别和联系
- Linux编程之《守护进程》
- ”运维离不开安全 安全没有运维也就没有价值“理论下的隐藏意义
- linux基础目录结构
- arm-linux交叉编译ACE
- 使用Nginx反向代理 让IIS和Tomcat等多个站点一起飞
- 正向代理与反向代理的区别
- 解决导航栏返回按钮与Pop手势冲突的问题
- Linux系统使用ps命令查看进程所占cpu和内存比例
- nginx常用命令
- 适合kali Linux 2.0 的源码(中科大,阿里云、163、上海交通大学源码)
- 海量数据的topK问题
- PYTHON的程序在LINUX后台运行
- windows环境下使用nginx
- Tomcat与Jdk的版本匹配
- opencv 在windows 7 上面不能打开视频的原因
- 通过设置nginx的client_max_body_size解决nginx+php上传大文件的问题