傳說中,南極有一片廣闊的冰原,在冰原下藏有史前文明的遺址。整個冰原被橫豎劃分成了很多個大小相等的方格。在這個冰原上有N個大小不等的矩形冰山,這些巨大的冰山有着和南極一樣古老的歷史,每個矩形冰山至少佔據一個方格,且其必定完整地佔據方格。冰山和冰山之間不會重疊,也不會有邊或點相連。以下兩種情況均是不可能出現的:
ACM探險隊在經過多年準備之後決定在這個冰原上尋找遺址。根據他們掌握的資料,在這個冰原上一個大小爲一格的深洞中,藏有一個由史前人類製作的開關。而唯一可以打開這個開關的是一個佔據接近一格的可移動的小冰塊。顯然,在南極是不可能有這樣小的獨立冰塊的,所以這塊冰塊也一定是史前文明的產物。他們在想辦法把這個冰塊推到洞裏去,這樣就可以打開一條通往冰原底部的通道,發掘史前文明的祕密。冰塊的起始位置與深洞的位置均不和任何冰山相鄰。
這個冰原上的冰面和冰山都是完全光滑的,輕輕的推動冰塊就可以使這個冰塊向前滑行,直到撞到一座冰山就在它的邊上停下來。冰塊可以穿過冰面上所有沒有冰山的區域,也可以從兩座冰山之間穿過(見下圖)。冰塊只能沿網格方向推動。
請你幫助他們以最少的推動次數將冰塊推入深洞中。
輸入格式
輸入文件第一行爲冰山的個數N (1<=N<=4000),第二行爲冰塊開始所在的方格座標X1,Y1,第三行爲深洞所在的方格座標X2,Y2,以下N行每行有四個數,分別是每個冰山所佔的格子左上角和右下角座標Xi1,Yi1,Xi2,Yi2
輸出格式
輸出文件僅包含一個整數,爲最少推動冰塊的次數。如果無法將冰塊推入深洞中,則輸出0。==================================================================
這題的幾個題解都說是離散化+寬搜,但我總覺的開一個8000*8000的數組不靠譜(64M啊!)。
我的做法:
這題如果把當中可以停的點當作節點,構圖,求個最短路就行了。關鍵是無法對點進行有效的編號,於是我想到了splay,通過一個query(x,y)函數返回對應點的指針(若該點不在容器中會自動生成一個新的點,把它的dis設成+Inf),這樣在spfa的隊列中只記下對應點的指針就可以了;剛開始的時候,spfa寫成了棧式,tle了,對於這個有特殊性的圖來說,棧式是速度最慢的,因爲邊權都是1,破壞了寬搜的那種最優性,如果寫成隊列式,搜到終點就可以exit了;由於不好確定隊列開多大,我隊列寫成了鏈表;還有就是判斷停止,我這題用樸素就可以過了,我用二分縮短枚舉範圍,但效率沒高多少,應該還可以用線段樹優化,但感覺沒想透,所以暫時沒用,在跟它類似的APIO-path里加上線段樹吧~
================================================
Code:type
link=^node;
node=record pre:link; ch:array[0..1] of link; x,y,dis:longint; end;
qlink=^qnode;
qnode=record x:link; next:qlink; end;
data=record x,low,high:longint; end;
arr=array[1..4000] of data;
var que,last:qlink;
root:link;
n,x1,y1,x2,y2:longint;
//============================================================================//
arr1,arr2,arr3,arr4:arr;
procedure insert(var a:arr;i,x,low,high:longint);
begin
a[i].x:=x;
a[i].low:=low;
a[i].high:=high;
end;
procedure sort(var a:arr;l,r:longint);
var i,j:longint; mid,tmp:data;
begin
i:=l; j:=r; mid:=a[(l+r)shr 1];
repeat
while (a[i].x<mid.x)do inc(i);
while (a[j].x>mid.x)do dec(j);
if i<=j then begin
tmp:=a[i]; a[i]:=a[j]; a[j]:=tmp;
inc(i); dec(j);
end;
until i>j;
if i<r then sort(a,i,r);
if l<j then sort(a,l,j);
end;
function up(x,y:longint;var tx:longint):boolean;{arr1}
var l,r,i,mid:longint;
begin
l:=1; r:=n;
while l<r do begin
mid:=(l+r)shr 1+1;
if arr1[mid].x<x then l:=mid
else r:=mid-1;
end;
tx:=-maxlongint;
for i:=l downto 1 do
if (arr1[i].x<x)and(arr1[i].low<=y)and(arr1[i].high>=y)then begin
tx:=arr1[i].x+1;
break;
end;
if (y=y2)and(x2>=tx)and(x2<=x)then tx:=x2;
if (tx=-maxlongint)or(tx=x)then exit(false) else exit(true);
end;
function down(x,y:longint;var tx:longint):boolean;{arr2}
var l,r,i,mid:longint;
begin
l:=1; r:=n;
while l<r do begin
mid:=(l+r)shr 1;
if arr2[mid].x>x then r:=mid
else l:=mid+1;
end;
tx:=maxlongint;
for i:=r to n do
if (arr2[i].x>x)and(arr2[i].low<=y)and(arr2[i].high>=y)then begin
tx:=arr2[i].x-1;
break;
end;
if (y=y2)and(x2<=tx)and(x2>=x)then tx:=x2;
if (tx=maxlongint)or(tx=x)then exit(false) else exit(true);
end;
function left(x,y:longint;var ty:longint):boolean;{arr4}
var l,r,i,mid:longint;
begin
l:=1; r:=n;
while l<r do begin
mid:=(l+r)shr 1+1;
if arr4[mid].x<y then l:=mid
else r:=mid-1;
end;
ty:=-maxlongint;
for i:=l downto 1 do
if (arr4[i].x<y)and(arr4[i].low<=x)and(arr4[i].high>=x)then begin
ty:=arr4[i].x+1;
break;
end;
if (x=x2)and(y2>=ty)and(y2<=y) then ty:=y2;
if (ty=-maxlongint)or(ty=y)then exit(false) else exit(true);
end;
function right(x,y:longint;var ty:longint):boolean;{arr3}
var l,r,i,mid:longint;
begin
l:=1; r:=n;
while l<r do begin
mid:=(l+r)shr 1;
if arr3[mid].x>y then r:=mid
else l:=mid+1;
end;
ty:=maxlongint;
for i:=r to n do
if (arr3[i].x>y)and(arr3[i].low<=x)and(arr3[i].high>=x)then begin
ty:=arr3[i].x-1;
break;
end;
if (x=x2)and(y2>=y)and(y2<=ty)then ty:=y2;
if (ty=maxlongint)or(ty=y)then exit(false)else exit(true);
end;
//============================================================================//
procedure rotate(x:link;k:longint);
var f:link;
begin
f:=x^.pre;
f^.ch[1-k]:=x^.ch[k]; if x^.ch[k]<>nil then x^.ch[k]^.pre:=f;
x^.pre:=f^.pre; if f^.pre<>nil then if f^.pre^.ch[0]=f then f^.pre^.ch[0]:=x else f^.pre^.ch[1]:=x;
x^.ch[k]:=f; f^.pre:=x; if f=root then root:=x;
end;
procedure splay(x,goal:link);
var y,z:link;
begin
while x^.pre<>goal do
if x^.pre^.pre=goal then
if x^.pre^.ch[0]=x then rotate(x,1)
else rotate(x,0)
else begin
y:=x^.pre; z:=y^.pre;
if z^.ch[0]=y then
if y^.ch[0]=x then begin rotate(y,1); rotate(x,1); end
else begin rotate(x,0); rotate(x,1); end
else if y^.ch[1]=x then begin rotate(y,0); rotate(x,0); end
else begin rotate(x,1); rotate(x,0); end;
end;
end;
function query(x,y:longint):link;
procedure search(var r:link);
begin
if r=nil then begin
new(r);
r^.x:=x;
r^.y:=y;
r^.dis:=maxlongint;
r^.ch[0]:=nil;
r^.ch[1]:=nil;
query:=r;
end else if r^.x<x then begin search(r^.ch[1]); r^.ch[1]^.pre:=r; end
else if r^.x>x then begin search(r^.ch[0]); r^.ch[0]^.pre:=r; end
else if r^.y<y then begin search(r^.ch[1]); r^.ch[1]^.pre:=r; end
else if r^.y>y then begin search(r^.ch[0]); r^.ch[0]^.pre:=r; end
else query:=r;
end;
begin
search(root);
root^.pre:=nil;
splay(query,nil);
end;
//============================================================================//
procedure push(x:link);
var p:qlink;
begin
new(p);
p^.x:=x;
p^.next:=nil;
if que=nil then begin
que:=p;
last:=p;
end else begin
last^.next:=p;
last:=p;
end;
end;
function pop:link;
begin
pop:=que^.x;
que:=que^.next;
end;
//============================================================================//
function spfa:longint;
var t:longint; p,q:link;
begin
que:=nil;
root:=nil;
q:=query(x1,y1);
q^.dis:=0;
push(q);
while que<>nil do begin
q:=pop;
with q^ do begin
if (x=x2)and(y=y2)then exit(dis);
if up(x,y,t) then begin
p:=query(t,y);
if p^.dis>dis+1 then begin
p^.dis:=dis+1;
push(p);
end;
end;
if down(x,y,t) then begin
p:=query(t,y);
if p^.dis>dis+1 then begin
p^.dis:=dis+1;
push(p);
end;
end;
if left(x,y,t) then begin
p:=query(x,t);
if p^.dis>dis+1 then begin
p^.dis:=dis+1;
push(p);
end;
end;
if right(x,y,t) then begin
p:=query(x,t);
if p^.dis>dis+1 then begin
p^.dis:=dis+1;
push(p);
end;
end;
end;
end;
q:=query(x2,y2);
if q^.dis=maxlongint then exit(0)
else exit(q^.dis);
end;
//
procedure main;
var i,tx1,tx2,ty1,ty2:longint;
begin
readln(n);
readln(x1,y1);
readln(x2,y2);
for i:=1 to n do begin
readln(tx1,ty1,tx2,ty2);
insert(arr1,i,tx2,ty1,ty2);
insert(arr2,i,tx1,ty1,ty2);
insert(arr3,i,ty1,tx1,tx2);
insert(arr4,i,ty2,tx1,tx2);
end;
sort(arr1,1,n);
sort(arr2,1,n);
sort(arr3,1,n);
sort(arr4,1,n);
write(spfa);
end;
begin
main;
end.