読者です 読者をやめる 読者になる 読者になる

Lilliput Steps

小さな一歩から着実に. 数学やプログラミングのことを書きます.

JOI春合宿 2008-day2 cheating

JOI 二分探索

問題文 : カンニング対策 (pdf注意, 3枚目)

解法 : 監視する装置の範囲の最大値を求めれば良いから, すべての装置の精度を等しいものとして考える.
すると, 端から貪欲的に装置を置いていける.
装置の範囲の最大値は, 二分探索で決めてやることで, O(Mlog(max(x, y)))時間でこの問題を解くことができる.

コード :

#include <cstdio>
#include <algorithm>

using namespace std;

int n, m;

typedef struct {
	int x, y;
} Point;

Point sx[200000], sy[200000];

bool compx(const Point &a, const Point &b)
{
	return (a.x < b.x);
}

bool compy(const Point &a, const Point &b)
{
	return (a.y < b.y);
}

bool canControl(int dmax)
{
	int piv = -1000000001;
	int lim = n;
	
	for (int i = 0; i < m; i++){
		if (piv + dmax < sx[i].x){
			piv = sx[i].x;
			lim--;
		}
		if (lim == -1){
			return (false);
		}
	}
	
	piv = -1000000001;
	
	for (int i = 0; i < m; i++){
		if (piv + dmax < sy[i].y){
			piv = sy[i].y;
			lim--;
		}
		if (lim == -1){
			return (false);
		}
	}
	
	return (true);
}


int main(void)
{
	int left, right, center;
	
	scanf("%d %d", &n, &m);
	
	for (int i = 0; i < m; i++){
		int tx, ty;
		scanf("%d %d", &tx, &ty);
		sx[i].x = sy[i].x = tx;
		sx[i].y = sy[i].y = ty;
	}
	sort(sx, sx + m, compx);
	sort(sy, sy + m, compy);
	
	left = 0, right = 1000000000;
	
	while (left != right){
		center = (left + right) / 2;
		
		if (canControl(center) == true){
			right = center;
		}
		else {
			left = center + 1;
		}
	}
	
	printf("%d\n", m ? left : right);
	
	return (0);
}