P3438 [POI2006]ZAB-Frogs

给出一个不一样的解法。不需要用到斜率优化等高级算法。

下文记 \(n=w_x,m=w_y\)。


首先,答案显然满足可二分性,因此二分答案 \(d\in [0,nm]\) 确定距离的平方。

这样我们将题目转化为:求起点到终点之间是否有一条路径使得任何一个点都不被圆心是整点且半径相同的若干个圆所覆盖。记 \(r=\sqrt d\)。如果处理出一个点是否被覆盖,那么可以 \(\mathcal{O}(nm)\) BFS 求出答案。

枚举每一竖列即 \(x\),显然覆盖到该列的圆的圆心 \(x_i\) 坐标满足 \((x_i-x)^2\leq d\) 即 \(x_i-r\leq x\leq x_i+r\)。将所有圆按照 \(x_i\) 从小到大排序,Two-pointers 维护即可。

如果直接考虑一个点被覆盖的圆会很难做。不妨转换思路,枚举能够覆盖这一竖列的所有圆,记圆心为 \((x_i,y_i)\ (x_i-r\leq x\leq x_i+r)\)。显然,它能覆盖到的第 \(x\) 列的所有点的纵坐标 \(y\) 形成了一段区间。差分计算线段覆盖即可。

当然这么做显然是过不去的,因为一共有 \(m\) 列,而枚举到的圆的个数为 \(\mathcal{O}(nm)\)。因此时间复杂度为 \(nm^2\log(nm)\)。


考虑优化上面的算法。注意到在枚举所有圆时,如果出现两个圆 \((x_1,y_1)\) 和 \((x_2,y_2)\) 满足 \(y_1=y_2\) 且 \(|x_1-x|>|x_2-x|\),那么我们根本不需要考虑第一个圆 \((x_1,y_1)\),因为它能覆盖到的第 \(x\) 列的所有点包含于 \((x_2,y_2)\) 能覆盖到的第 \(x\) 列的所有点。这是很显然的,因为前者的 \(y\) 需要满足 \(|y-y_1|\leq \sqrt {d-(x_1-x)^2}\),后者的 \(y\) 需要满足 \(|y-y_2|\leq \sqrt {d-(x_2-x)^2}\),而 \(\sqrt {d-(x_1-x)^2}<\sqrt {d-(x_2-x)^2}\)。

因此,对于每一行 \(y\),维护圆心纵坐标为 \(y\) 且与当前 \(x\) 距离最小的圆,那么最终我们只需枚举 \(\mathcal{O}(n)\) 个圆即可。具体地,维护 \(n\) 个存横坐标 \(x_i\) 的队列,在 Two-pointers 添加或删除一个圆 \((x_i,y_i)\) 时,对第 \(y_i\) 个队列进行添加或删除操作即可。此外,移动到下一列 \(x\gets x+1\) 时,不断弹出每个队的队首元素直至队列只剩下一个元素或队列队首横坐标与 \(x+1\) 的距离小于队首下一个横坐标与 \(x+1\) 的距离。

时间复杂度为 \(\mathcal{O}(nm\log (nm))\)。

#include <bits/stdc++.h>
using namespace std; #define gc getchar()
#define pii pair <int,int>
#define fi first
#define se second
#define mem(x,v) memset(x,v,sizeof(x)) inline int read(){
int x=0,sign=0; char s=gc;
while(!isdigit(s))sign|=s=='-',s=gc;
while(isdigit(s))x=(x<<1)+(x<<3)+(s-'0'),s=gc;
return sign?-x:x;
} const int N=1e3+5; int n,m,leg[N][N];
int stx,sty,edx,edy,num;
struct point{
int x,y;
}p[N*N],mp[N][N]; bool vis[N][N];
pii q[N*N];
bool bfs(){
if(vis[stx][sty]==1)return 0;
int h=1,tl=0; q[++tl]={stx,sty},vis[stx][sty]=1;
while(h<=tl){
int x=q[h].fi,y=q[h++].se;
if(x==edx&&y==edy)return 1;
if(!vis[x+1][y])vis[x+1][y]=1,q[++tl]={x+1,y};
if(!vis[x-1][y])vis[x-1][y]=1,q[++tl]={x-1,y};
if(!vis[x][y+1])vis[x][y+1]=1,q[++tl]={x,y+1};
if(!vis[x][y-1])vis[x][y-1]=1,q[++tl]={x,y-1};
} return 0;
} int dist(int a,int b,int c,int d){return (a-c)*(a-c)+(b-d)*(b-d);} int d[N][N],hd[N],len[N],s[N];
void add(point x){d[x.y][len[x.y]++]=x.x;}
void del(point x){if(d[x.y][hd[x.y]]==x.x)hd[x.y]++;}
void update(int y,int x){while(d[y][hd[y]+1]&&abs(d[y][hd[y]]-x)>=abs(d[y][hd[y]+1]-x))hd[y]++;} bool check(int x){
int dis=sqrt(x);
mem(vis,0),mem(d,0),mem(hd,0),mem(len,0);
for(int i=0;i<=max(n,m);i++)vis[0][i]=vis[i][0]=vis[n+1][i]=vis[i][m+1]=1;
for(int i=1,l=1,r=1;i<=n;i++,mem(s,0)){
while(r<=num&&i+dis>=p[r].x)add(p[r++]);
while(l<=num&&i-dis>p[l].x)del(p[l++]);
for(int j=1;j<=m;j++){
update(j,i); int xx=d[j][hd[j]];
if(!xx)continue;
int radius=sqrt(x-(xx-i)*(xx-i)),l=j-radius,r=j+radius+1;
s[max(1,l)]++,s[min(m+1,r)]--;
} for(int j=1;j<=m;j++)vis[i][j]=(s[j]+=s[j-1])>0;
} return bfs();
} int main(){
cin>>n>>m>>stx>>sty>>edx>>edy>>num;
for(int i=1;i<=num;i++)p[i].x=read(),p[i].y=read(),mp[p[i].x][p[i].y]=p[i];
for(int i=1,cnt=0;i<=n;i++)for(int j=1;j<=m;j++)if(mp[i][j].x!=0)p[++cnt]=mp[i][j];
int l=-1,r=2e6;
while(l<r){
int m=(l+r>>1)+1;
check(m)?l=m:r=m-1;
} cout<<l+1<<endl;
return 0;
}

P3438 [POI2006]ZAB-Frogs的更多相关文章

  1. 洛谷 P3438 - [POI2006]ZAB-Frogs(乱搞/李超线段树)

    题面传送门 首先一眼二分答案,我们假设距离 \((i,j)\) 最近的 scarefrog 离它的距离为 \(mn_{i,j}\),那么当我们二分到 \(mid\) 时我们显然只能经过 \(mn_{i ...

  2. 分布式系统理论进阶 - Raft、Zab

    引言 <分布式系统理论进阶 - Paxos>介绍了一致性协议Paxos,今天我们来学习另外两个常见的一致性协议——Raft和Zab.通过与Paxos对比,了解Raft和Zab的核心思想.加 ...

  3. paxos(chubby) vs zab(Zookeeper)

    参考: Zookeeper的一致性协议:Zab Chubby&Zookeeper原理及在分布式环境中的应用 Paxos vs. Viewstamped Replication vs. Zab ...

  4. ZooKeeper之ZAB协议

    ZooKeeper为高可用的一致性协调框架,自然的ZooKeeper也有着一致性算法的实现,ZooKeeper使用的是ZAB协议作为数据一致性的算法,ZAB(ZooKeeper Atomic Broa ...

  5. POJ 1659 Frogs' Neighborhood(Havel-Hakimi定理)

    题目链接: 传送门 Frogs' Neighborhood Time Limit: 5000MS     Memory Limit: 10000K Description 未名湖附近共有N个大小湖泊L ...

  6. CF# Educational Codeforces Round 3 F. Frogs and mosquitoes

    F. Frogs and mosquitoes time limit per test 2 seconds memory limit per test 512 megabytes input stan ...

  7. 第三章 深入 ZAB 协议

    上一节介绍了ZAB协议的内容,本节将从系统模型.问题描述.算法描述和运行分析四方面来深入了解 ZAB 协议. 系统模型 在一个由一组进程 n ={P1,P2,...Pn}组成的分布式系统中,每一个进程 ...

  8. 第二章 ZAB协议介绍

    ZAB ( ZooKeeper Atomic Broadcast , ZooKeeper 原子消息广播协议)是zookeeper数据一致性的核心算法. ZAB 协议并不像 Paxos 算法那样,是一种 ...

  9. 【BZOJ】【1520】【POI2006】Szk-Schools

    网络流/费用流 比较裸的一道题 依旧是二分图模型,由源点S连向每个学校 i (1,0),「注意是连向第 i 所学校,不是连向学校的标号m[i]……唉这里WA了一次」 然后对于每所学校 i 连接 j+n ...

随机推荐

  1. 【Java虚拟机2】Java类加载机制

    前言 JAVA代码经过编译从源码变为字节码,字节码可以被JVM解读,使得JVM屏蔽了语言级别的限制.才有了现在的kotlin.Scala.Clojure.Groovy等语言. 字节码文件中描述了类的各 ...

  2. 【Java虚拟机1】Java字节码文件格式入门

    第一次学习看字节码文件,这个对工作没什么用,但是会提升内功. 首先介绍两个IDEA插件以及使用: BinEd:以16进制格式查看class文件 使用方法:右键class文件,点击Open as bin ...

  3. 【UE4 C++】碰撞检测与事件绑定

    概念 碰撞对象通道与预设 默认提供碰撞对象类型,如 WorldStatic.WorldDynamic等.允许用户自定义 默认提供碰撞预设,如 NoCollision.BloackAll.Overlap ...

  4. the Agiles Scrum Meeting 6

    会议时间:2020.4.14 20:00 1.每个人的工作 今天已完成的工作 增量组:开发广播正文展开收起功能 issues:增量组:广播正文展开收起功能实现 完善组:修复冲刺部分的bug issue ...

  5. git常用的一些简单命令

    1.如果一个文件被修改了,但是还没有使用 git add 命令,此时想取消这次修改,需要执行的命令如下: git checkout -- 文件名 2.如果一个文件执行了 git add ,此时想取消这 ...

  6. 设置nginx进程可打开最大的文件数

    涉及到的nginx配置参数: worker_processes: 表示操作系统启动多少个工作进程在运行,一般这个参数设置成CPU核数的倍数 worker_connections:表示nginx的工作进 ...

  7. Noip模拟79 2021.10.17(题目名字一样)

    T1 F 缩点缩成个$DAG$,然后根据每个点的度数计算期望值 1 #include<cstdio> 2 #include<cstring> 3 #include<vec ...

  8. 2021.8.3考试总结[NOIP模拟29]

    T1 最长不下降子序列 数据范围$1e18$很不妙,但模数$d$只有$150$,考虑从这里突破. 计算的式子是个二次函数,结果只与上一个值有关,而模$d$情况下值最多只有$150$个,就证明序列会出现 ...

  9. 线程池系列二:一张动图,彻底懂了execute和submit

    ​ 我们知道线程池通过execute方法执行提交的Runnable任务,但Runnable只是执行任务,没有返回任何信息. [线程池原理:线程池原来是个外包公司,打工人我悟了] 若是我们想在异步执行完 ...

  10. 字符串折叠&压缩(区间DP)

    字符串折叠 题目描述 折叠的定义如下: 一个字符串可以看成它自身的折叠.记作S = S X(S)是X(X>1)个S连接在一起的串的折叠.记作X(S) = SSSS-S(X个S). 如果A = A ...