传送门

曼哈顿距离好像不好直接算,我们可以把牛的坐标转化一下以方便计算距离

(x,y) --> (x+y,x-y) 那么距离就可以表示成 $max(\left |x_1-x_2  \right |,\left | y_1-y_2 \right |)$

自己在草稿纸上算一下就知道了,(因为之后我们会按转化后的横坐标排序,所以式子会少一种情况)

(以下横纵坐标均已转化)

所以可以考虑这样一种方案,把牛按横坐标排序

然后考虑总左到右枚举牛加入队列:每次加入一只牛,与队列里的其他牛比较一下纵坐标距离,这样能够保证每只牛都两两匹配过

并且队列保证当前的牛的横坐标与队列内其他牛的横坐标之差不大于C(即与队列最左的牛横坐标之差不大于C)

但是复杂度会爆炸,考虑优化

可以发现,我们匹配时只要找纵坐标大于它的最小的牛和纵坐标小于它的最大的牛,因为如果它能匹配队列的其他牛A,那么那两只牛也一定至少有一只能匹配A

就是在队列里求一个值的前驱后继,那么很容易想到用平衡树 multiset 来维护

可能会有疑问此时的前驱后继是可以和原数相同的(转化后的横纵坐标可能相同),如果强行维护好像很麻烦的样子

但是对于相同的点显然前驱后继至少有一个会考虑到,那么对答案就不会有影响了

然后并查集维护联通块就好了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=1e5+;
int n,C;
int fa[N],cnt[N];//cnt是当前每个块的大小
inline int find(int x) { return x==fa[x] ? x : fa[x]=find(fa[x]); }
inline void uni(int x,int y)//并查集合并两个块
{
int xa=find(x),xb=find(y);
if(xa==xb) return;
fa[xa]=xb; cnt[xb]+=cnt[xa]; cnt[xa]=;
}
struct data//存转化后的横纵坐标
{
int x,y,id;
data () { x=y=id=; }
inline bool operator < (const data &tmp) const {//multiset内按纵坐标排序
return y<tmp.y;
}
}d[N];
inline bool cmp(const data &a,const data &b){ return a.x<b.x; }//按横坐标排序
int fir;//队列的最左边位置
multiset <data> s;
multiset <data>::iterator it;
void slove()
{
sort(d+,d+n+,cmp);//排序
fir=; s.insert(d[]);//第一个直接加进去
data t; t.y=2e9+; s.insert(t); t.y=-(2e9+); s.insert(t);//防止指针越界
for(int i=;i<=n;i++)
{
while(d[i].x-d[fir].x>C) s.erase(s.find(d[fir])),fir++;//更新队列
it=s.lower_bound(d[i]);//找后继
t=*it; --it;//找前驱
if(t.y-d[i].y<=C) uni(t.id,d[i].id);//尝试与后继合并
t=*it;
if(d[i].y-t.y<=C) uni(t.id,d[i].id);//尝试与前驱合并
s.insert(d[i]);//别忘了加到multiset里
}
}
int main()
{
int a,b;
n=read(); C=read();
for(int i=;i<=n;i++)
{
a=read(),b=read();
d[i].x=a+b; d[i].y=a-b; d[i].id=i;
fa[i]=i; cnt[i]=;//初始化
}
slove();
int mx=,tot=;//计算块和最大块大小
for(int i=;i<=n;i++)
if(cnt[i])
{
mx=max(mx,cnt[i]);
tot++;
}
printf("%d %d",tot,mx);
return ;
}

P2906 [USACO08OPEN]牛的街区Cow Neighborhoods的更多相关文章

  1. bzoj1604 / P2906 [USACO08OPEN]牛的街区Cow Neighborhoods

    P2906 [USACO08OPEN]牛的街区Cow Neighborhoods 考虑维护曼哈顿距离:$\left | x_{1}-x_{2} \right |+\left | y_{1}-y_{2} ...

  2. 洛谷 P2906 [USACO08OPEN]牛的街区Cow Neighborhoods | Set+并查集

    题目: https://www.luogu.org/problemnew/show/P2906 题解: 垃圾水题 #include<cstdio> #include<algorith ...

  3. 「洛谷P2906」[USACO08OPEN]牛的街区Cow Neighborhoods 解题报告

    P2906 [USACO08OPEN]牛的街区Cow Neighborhoods 题目描述 Those Who Know About Cows are aware of the way cows gr ...

  4. [USACO08OPEN]牛的街区Cow Neighborhoods

    题目描述: luogu 题解: 技巧题. 曼哈顿距离:$|x1-x2|+|y1-y2|$ 切比雪夫距离:$\max(|x1-x2|,|y1-y2|)$ 曼哈顿距离转切比雪夫距离:$(x,y)-> ...

  5. bzoj1623 / P2909 [USACO08OPEN]牛的车Cow Cars

    P2909 [USACO08OPEN]牛的车Cow Cars 显然的贪心. 按速度从小到大排序.然后找车最少的车道,查询是否能填充进去. #include<iostream> #inclu ...

  6. 洛谷 P2909 [USACO08OPEN]牛的车Cow Cars

    传送门 题目大意: m个车道. 如果第i头牛前面有k头牛,那么这头牛的最大速度会 变为原本的速度-k*D,如果速度小于l这头牛就不能行驶. 题解:贪心 让初始速度小的牛在前面 代码: #include ...

  7. [USACO08OPEN]牛的车Cow Cars

    题目描述 N (1 <= N <= 50,000) cows conveniently numbered 1..N are driving in separate cars along a ...

  8. [BZOJ1604][Usaco2008 Open]Cow Neighborhoods 奶牛的邻居

    [BZOJ1604][Usaco2008 Open]Cow Neighborhoods 奶牛的邻居 试题描述 了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的N(1≤N≤100000)只奶牛,你会发 ...

  9. bzoj 1604 [Usaco2008 Open]Cow Neighborhoods 奶牛的邻居(set+并查集)

    Description 了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的N(1≤N≤100000)只奶牛,你会发现她们已经结成了几个“群”.每只奶牛在吃草的 时候有一个独一无二的位置坐标Xi,Yi( ...

随机推荐

  1. myeclipse.ini

    myeclipse10 32位 我的配置 #utf8 (do not remove) #utf8 (do not remove) -startup ../Common/plugins/org.ecli ...

  2. VS2012新建网站出现(1)的解决方案

    1.用记事本打开以下文件: D:\Users\lyn\Documents\IISExpress\config\applicationhost.config 2.删除sites结点下的所有site结点:

  3. jquery获取元素在文档中的位置信息以及滚动条位置(转)

    jquery获取元素在文档中的位置信息以及滚动条位置 http://blog.csdn.net/qq_34095777/article/details/78750886     原文链接 原创 201 ...

  4. winform 公共控件 ListView

    //数据显示,刷新 public void F5() { listView1.Items.Clear(); List<Students> Stu = new StudentsData(). ...

  5. SQl Server 与数据库的第一次相遇

    数据库就是 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,简单说就是存储在硬盘上的文件. 市面上常见数据库有<关系数据库系统>: ORACLE(甲骨文).DB2.S ...

  6. Windows libQGLViewer2.7.0,libQGLViewer2.6.2与g2o20160427, g2o20170730编译生成G2O

    1. Win10, VS2013, libQGLViewer2.6.2 和 QT5.6.3编译时候会出错,初步判断libQGLViewer2.6.2不支持QT5 错误 error LNK1120: 个 ...

  7. 算法Sedgewick第四版-第1章基础-021一双向链表,在遍历时可修改、删除元素

    package algorithms.ADT; /*************************************************************************** ...

  8. Linux kdb命令

    一.简介 Linux 内核调试器(KDB)允许您调试 Linux 内核.这个恰如其名的工具实质上是内核代码的补丁,它允许高手访问内核内存和数据结构.KDB 的主要优点之一就是它不需要用另一台机器进行调 ...

  9. ARC102E Stop. Otherwise...

    传送门 题目大意 现在有n个k面的骰子,问在i=2~2*k的情况下,任意两个骰子向上那一面的和不等于i的方案数是多少. 分析 这道题具体做法见这个博客. 至于k2的值为啥是那个自己画画图就明白了. 代 ...

  10. HDU 2102 A计划 (BFS或DFS)

    题意:中文题. 析:是一个简单的搜索,BFS 和 DFS都可行, 主要是这个题有一个坑点,那就是如果有一层是#,另一个层是#或者*,都是过不去的,就可以直接跳过, 剩下的就是一个简单的搜索,只不过是两 ...