E. Fire in the City
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
The capital of Berland looks like a rectangle of size n × m of the square blocks of same size.
Fire!
It is known that k + 1 blocks got caught on fire (k + 1 ≤ n·m). Those blocks are centers of ignition. Moreover positions of k of these centers are known and one of these stays unknown. All k + 1 positions are distinct.
The fire goes the following way: during the zero minute of fire only these k + 1 centers of ignition are burning. Every next minute the fire goes to all neighbouring blocks to the one which is burning. You can consider blocks to burn for so long that this time exceeds the time taken in the problem. The neighbouring blocks are those that touch the current block by a side or by a corner.
Berland Fire Deparment wants to estimate the minimal time it takes the fire to lighten up the whole city. Remember that the positions of k blocks (centers of ignition) are known and (k + 1)-th can be positioned in any other block.
Help Berland Fire Department to estimate the minimal time it takes the fire to lighten up the whole city.
Input
The first line contains three integers n, m and k (1 ≤ n, m ≤ 109, 1 ≤ k ≤ 500).
Each of the next k lines contain two integers xi and yi (1 ≤ xi ≤ n, 1 ≤ yi ≤ m) — coordinates of the i-th center of ignition. It is guaranteed that the locations of all centers of ignition are distinct.
Output
Print the minimal time it takes the fire to lighten up the whole city (in minutes).
Examples
Input
7 7 3
1 2
2 1
5 5
Output
3
Input
10 5 1
3 3
Output
2
题意 : 给你一个空图 有k+1个着火点, 其中有k个着火点已经给出,剩下的那一个着火点由你来摆放。 着火点每一秒向外扩充一圈。 问你最少多少秒能使整个图全部被点着。
part 1
首先,我们先考虑最简单的问题, 如果这个图是一维的,那么就是个经典的二分贪心模型题。
part2
再者,在不考虑数据范围的前提下想一下这题的解法,原本是一维中是求每个点可以覆盖的长度。 现在是求每个点可以覆盖的面积。 可以(看)联(题)想(解)得出,解决这个问题可以使用扫描线(扫描线可以解决面积覆盖问题)
part 3
最后,看到图的范围丧心病狂的达到了1e9*1e9 但是着火点最多只有500个 。 这种数据范围是很明显的离散化模型题。
part4
思路贼清晰,就是几个简单的模型凑在一起。 。
but!@ 我写了好久无法实现。。。。 太菜了。
最后去cf上膜了别人的代码后才知道怎么写。
二分的判断函数可以这么实现
一、 处理完所有直线 每条直线弄成[ l , r ) 这种形式,并将端点加入哈希表,上界权值设为-1 下界权值设为1
二、离散化,离散化之后,我们考虑离散化后每个点的实际意义。
每个点不仅仅是一个点了,他可能代表一条线段。 所以才要将线段写成半闭半开区间的形式。 离散化要注意一点 为了保证离散化的正确性,我们需要加入参照物,既边界。
三. 定义四个变量 分别代表第k+1个着火点必须点燃的部分的边界。
这个边界如何更新呢? 当我们每扫完一层线段后 我们进行一次遍历,
检测是否有区间没有被覆盖。 对于没有覆盖的区间,边界必须将其包含。
四, 最后检查 如果边界差值大于2*d 则说明这个d肯定不合法,反之则合法。
具体实现见代码。 嗯 代码确实丑了点
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define mkp make_pair
#define fi first
#define se second
#define ll long long
#define M 1000000007
#define all(a) a.begin(), a.end()
class line
{
public:
int h,l,r,s;// 高度 左边界 右边界 上下界
line(int h,int l,int r,int s):h(h),l(l),r(r),s(s){}
bool operator < (const line &b) const
{
return h<b.h;
}
};
int x[1005],y[1005];
vector <line> VL;// 存扫描线
vector <int> VH;// 存哈希表
int cnt[1005];
int n,m,k;
bool check(int d)
{
VL.clear();
VH.clear();
VH.push_back(1),VH.push_back(m+1);
VL.push_back(line(1,1,1,1));
VL.push_back(line(n+1,1,1,1));// 防止越界 添加俩无用边
for(int i=1;i<=k;i++)
{
VL.push_back(line(max(1, x[i] - d), max(1, y[i] - d), min(y[i] + d + 1, m + 1), 1));
VL.push_back(line(min(n + 1, x[i] + d + 1), max(1, y[i] - d), min(y[i] + d + 1, m + 1), -1));
VH.push_back(max(1, y[i] - d));
VH.push_back(min(y[i] + d + 1, m + 1));
}
sort(VH.begin(),VH.end());
VH.erase(unique(VH.begin(),VH.end()),VH.end());
sort(VL.begin(),VL.end());
int L=1<<30,R=-1,U=-1,D=1<<30;
memset(cnt,0,sizeof cnt);
for(int i=0,j=0;i<VL.size();i=j)
{
while(j<VL.size() && VL[i].h==VL[j].h)
{
int l=lower_bound(VH.begin(),VH.end(),VL[j].l)-VH.begin();
int r=lower_bound(VH.begin(),VH.end(),VL[j].r)-VH.begin();
for(int k= l;k<r;k++) cnt[k]+=VL[j].s;
j++;
}
if(VL[i].h<=n)
{
for(int k=0;k<VH.size()-1;k++)
{
if(cnt[k]<=0)
{
U=max(U,VH[k+1]-1);
D=min(D,VH[k]);
R=max(R,VL[j].h-1);
L=min(L,VL[i].h);
}
}
}
}return R - L <= 2 * d && U - D <= 2 * d;
}
int main()
{
//freopen("input.txt","r",stdin);
scanf("%d %d %d",&n,&m,&k);
for(int i=1;i<=k;i++)
{
scanf("%d %d",&x[i],&y[i]);
}
int l=-1,r=max(n,m);
while(l<r)
{
int d=(l+r)>>1;
if(check(d))
r=d;
else l=d+1;
}
cout<<l<<endl;
}
本文探讨了一个城市火灾蔓延模型问题,通过二分贪心、扫描线及离散化等算法解决复杂场景下最小时间估算问题。

773

被折叠的 条评论
为什么被折叠?



