POJ3179 Corral the Cows——线段树+离散化

算法讨论:

先按照y坐标排好序。二分答案,利用线段树判断是否可行。

这算不算是离散化呢?算是广义的离散化吧。

开始的时候没有更新,后来意识到错误后加上了更新反而错了,于是就偷了个懒把线段树build了log10000次,这样时间复杂度就变成了(log10000)^2*10000,过得很纠结……

其实不用build那么多次线段树的。

代码:

program corral;//By_Thispoet

const

	maxn=505;maxx=10005;

var

	i,j,p,c,n,mid,left,right,ans,k	:longint;

	tree							:array[0..maxx*10]of record l,r,num:longint;end;

	x,y								:array[0..maxn]of longint;



procedure swap(var i,j:longint);

begin

	if i<>j then begin i:=i xor j;j:=i xor j;i:=i xor j;end;

end;



procedure qsort(l,r:longint);

var i,j,k:longint;

begin

	i:=l;j:=r;k:=y[i+random(j-i+1)];

	repeat

		while y[i]<k do inc(i);while y[j]>k do dec(j);

		if i<=j then begin

			swap(x[i],x[j]);swap(y[i],y[j]);inc(i);dec(j);

		end;

	until i>j;

	if l<j then qsort(l,j);if i<r then qsort(i,r);

end;



procedure build_tree(code,l,r:longint);

var mid:longint;

begin

	tree[code].l:=l;tree[code].r:=r;tree[code].num:=0;

	if l+1>=r then exit;mid:=(l+r)>>1;

	build_tree(code*2,l,mid);build_tree(code*2+1,mid,r);

end;



procedure insert_tree(code,l,r,data:longint);

var mid:longint;

begin

	if (tree[code].l=l)and(tree[code].r=r) then begin

		inc(tree[code].num,data);exit;

	end;mid:=(tree[code].l+tree[code].r)>>1;

	if mid>=r then insert_tree(code*2,l,r,data) else insert_tree(code*2+1,l,r,data);

	tree[code].num:=tree[code*2].num+tree[code*2+1].num;

end;



function count(code,l,r:longint):longint;

var mid:longint;

begin

	if (tree[code].l=l)and(tree[code].r=r) then exit(tree[code].num);

	mid:=(tree[code].l+tree[code].r)>>1;

	if mid>=r then exit(count(code*2,l,r)) else if mid<=l then exit(count(code*2+1,l,r));

	exit(count(code*2,l,mid)+count(code*2+1,mid,r));

end;



function min(i,j:longint):longint;

begin

	if i<j then exit(i);exit(j);

end;



function check(pos:longint):boolean;

begin

	if pos=0 then exit(false);p:=0;

	for i:=1 to n do begin

		while (p<n)and (y[p+1]-y[i]<pos) do begin

			inc(p);insert_tree(1,x[p]-1,x[p],1);

		end;

		if p-i+1>=c then begin

			for j:=i to p do if count(1,x[j]-1,min(x[j]+pos-1,maxx))>=c then exit(true);

		end;

		insert_tree(1,x[i]-1,x[i],-1);

	end;

	exit(false);

end;



begin

	readln(c,n);randomize;

	for i:=1 to n do readln(x[i],y[i]);qsort(1,n);p:=0;

	left:=0;right:=maxx;

	while left<=right do begin

		mid:=(left+right)>>1;

		build_tree(1,0,maxx);

		if check(mid) then begin

			right:=mid-1;ans:=mid;

		end else left:=mid+1;

	end;

	writeln(ans);

end.

你可能感兴趣的:(poj)