001.
Unit Railroad;
002.
{$Mode ObjFPC}
003.
Interface
004.
TYPE
005.
TInts = Array
of
LongInt;
006.
007.
Function Plan_Roller_Coaster (S, T : TInts): Int64;
008.
009.
Implementation
010.
CONST
011.
MinX =
1
;
012.
MaxX =
1000
*
1000
*
1000
;
013.
014.
TYPE
015.
TDSF = Object
016.
Id, Rank : TInts;
017.
Size : LongWord;
018.
Constructor Create (N : LongWord);
019.
Function Get (U : LongWord): LongWord;
020.
Function Merge (U, V : LongWord): Boolean;
021.
End;
022.
TEntry = Record Key, Value : LongWord; End;
023.
THeap = Object
024.
Data : Array
of
TEntry;
025.
Size : LongWord;
026.
Constructor Create (Capacity : LongWord);
027.
Procedure Push (Key, Value : LongWord);
028.
Function Pop (): TEntry;
029.
Private
030.
Procedure Up (U : LongWord);
031.
Procedure Down (U : LongWord);
032.
Procedure Swap (U, V : LongWord); Inline;
033.
End;
034.
035.
036.
Constructor TDSF
.
Create (N : LongWord);
037.
Var
038.
i : LongWord;
039.
Begin
040.
Size := N;
041.
SetLength(Id, N);
042.
SetLength(Rank, N);
043.
For i:=
1
To N Do Begin
044.
Id[i-
1
] := i-
1
;
045.
Rank[i-
1
] :=
0
;
046.
End;
047.
End;
048.
049.
Function TDSF
.
Get (U : LongWord): LongWord;
050.
Begin
051.
If Id[U] <> U
052.
Then Id[U] := Get( Id[U] );
053.
Exit( Id[U] );
054.
End;
055.
056.
Function TDSF
.
Merge (U, V : LongWord): Boolean;
057.
Begin
058.
U := Get(U); V := Get(V);
059.
If U = V
060.
Then Exit(False);
061.
If Rank[U] = Rank[V]
062.
Then Inc( Rank[U] );
063.
If Rank[U] < Rank[V]
064.
Then Id[U] := V
065.
Else Id[V] := U;
066.
Dec(Size);
067.
Exit(True);
068.
End;
069.
070.
071.
Function Entry (Key, Value : LongWord): TEntry;
072.
Begin
073.
Result
.
Key := Key;
074.
Result
.
Value := Value;
075.
End;
076.
077.
078.
Constructor THeap
.
Create (Capacity : LongWord);
079.
Begin
080.
SetLength(Data, Capacity);
081.
Size :=
0
;
082.
End;
083.
084.
Procedure THeap
.
Push (Key, Value : LongWord);
085.
Begin
086.
Data[Size] := Entry(Key, Value);
087.
Inc(Size);
088.
Up(Size-
1
);
089.
End;
090.
091.
Function THeap
.
Pop (): TEntry;
092.
Begin
093.
Result := Data[
0
];
094.
Swap(
0
, Size-
1
);
095.
Dec(Size);
096.
Down(
0
);
097.
End;
098.
099.
Procedure THeap
.
Up (U : LongWord);
100.
Var
101.
V : LongWord;
102.
Begin
103.
While (U >
0
) Do Begin
104.
V := (U+
1
)
div
2
-
1
;
105.
If Data[V].Key < Data[U].Key
106.
Then Break;
107.
Swap(U, V);
108.
U := V;
109.
End;
110.
End;
111.
112.
Procedure THeap
.
Down (U : LongWord);
113.
Var
114.
V, W : LongWord;
115.
Begin
116.
V := (U+
1
) *
2
-
1
;
117.
While V < Size Do Begin
118.
W := V+
1
;
119.
If W = Size
120.
Then W := V;
121.
If Data[W].Key < Data[V].Key
122.
Then V := W;
123.
If Data[U].Key < Data[V].Key
124.
Then Break;
125.
Swap(U, V);
126.
U := V;
127.
V := (U+
1
) *
2
-
1
;
128.
End;
129.
End;
130.
131.
Procedure THeap
.
Swap (U, V : LongWord);
132.
Var
133.
Buff : TEntry;
134.
Begin
135.
Buff := Data[U];
136.
Data[U] := Data[V];
137.
Data[V] := Buff;
138.
End;
139.
140.
141.
Procedure ToSet (Var A : TInts);
142.
Var
143.
Heap : THeap;
144.
X, M : LongWord;
145.
Begin
146.
Heap
.
Create( Length(A) );
147.
For X
in
A
148.
Do Heap
.
Push(X, X);
149.
M :=
0
;
150.
While Heap
.
Size >
0
Do Begin
151.
X := Heap
.
Pop().Value;
152.
If (M >
0
)
and
(A[M-
1
] = X)
153.
Then Continue;
154.
A[M] := X;
155.
Inc(M);
156.
End;
157.
SetLength(A, M);
158.
End;
159.
160.
Function Find (Const Points : TInts; X : LongWord): LongWord;
161.
Var
162.
L, R : LongWord;
163.
Begin
164.
L :=
0
;
165.
R := Length(Points);
166.
While L+
1
< R
167.
Do If Points[(L+R)
div
2
] > X
168.
Then R := (L+R)
div
2
169.
Else L := (L+R)
div
2
;
170.
Exit(L);
171.
End;
172.
173.
Function Plan_Roller_Coaster (S, T : TInts): Int64;
174.
Var
175.
DSF : TDSF;
176.
Edges : THeap;
177.
Points, D : TInts;
178.
Edge : TEntry;
179.
Opened : Int64;
180.
N, M, i, U, V, DX : LongWord;
181.
Begin
182.
N := Length(S);
183.
SetLength(S, N+
1
); S[N] := MaxX;
184.
SetLength(T, N+
1
); T[N] := MinX;
185.
SetLength(Points,
2
*N+
2
);
186.
M :=
0
;
187.
For i:=
0
To N Do Begin
188.
Points[M] := S[i];
189.
Points[M+
1
] := T[i];
190.
Inc(M,
2
);
191.
End;
192.
ToSet(Points);
193.
M := Length(Points);
194.
DSF
.
Create(M);
195.
SetLength(D, M);
196.
FillChar(D[
0
], M*SizeOf(D[
0
]),
$00
);
197.
For i:=
0
To N Do Begin
198.
U := Find(Points, S[i]); V := Find(Points, T[i]);
199.
DSF
.
Merge(U, V);
200.
Inc( D[U] );
201.
Dec( D[V] );
202.
End;
203.
Result :=
0
;
204.
Opened :=
0
;
205.
Edges
.
Create(M);
206.
For i:=
1
To M-
1
Do Begin
207.
Inc(Opened, D[i-
1
]);
208.
DX := Points[i] - Points[i-
1
];
209.
If Opened <>
0
Then Begin
210.
DSF
.
Merge(i-
1
, i);
211.
If Opened >
0
212.
Then Inc(Result, Opened*DX);
213.
End Else Edges
.
Push(DX, i-
1
);
214.
End;
215.
If Opened <> -D[M-
1
]
216.
Then Halt(
1
);
217.
While DSF
.
Size >
1
Do Begin
218.
Edge := Edges
.
Pop();
219.
U := Edge
.
Value;
220.
If DSF
.
Get(U) <> DSF
.
Get(U+
1
) Then Begin
221.
Inc(Result, Edge
.
Key);
222.
DSF
.
Merge(U, U+
1
);
223.
End;
224.
End;
225.
End;
226.
227.
END.