fork download
  1. (* (C) I. Kakoulidis *)
  2. {$mode objfpc}{$H+}{$J-}
  3. {$ASSERTIONS ON}
  4. {$warnings on}
  5. {$hints on}
  6. {$R+}{$Q+}
  7.  
  8. uses SysUtils;
  9.  
  10. type
  11. generic TTreapNode<T> = class
  12. private
  13. // Key
  14. FKey: T;
  15. // Random heap priority
  16. FPriority: extended;
  17. // Number of nodes in subtree
  18. FSize: SizeUInt;
  19. // Left subtree reference
  20. FLeft: TTreapNode;
  21. // Right subtree reference
  22. FRight: TTreapNode;
  23. public
  24. (* Tree node constructor. *)
  25. constructor Create(const k: T);
  26.  
  27. (* Tree node destructor. *)
  28. destructor Destroy; override;
  29.  
  30. (* Returns number of keys in the tree rooted at @code(node). *)
  31. class function GetSize(const node: TTreapNode): SizeUInt; inline;
  32.  
  33. (* Recalculates number of keys in the tree rooted at @code(node) after insert, delete operations. *)
  34. class procedure UpdateSize(const node: TTreapNode); inline;
  35.  
  36. (* Creates new tree from two trees, where @code(Min(r) >= Max(l)). *)
  37. class function Meld(l, r: TTreapNode): TTreapNode;
  38.  
  39. (* Divides tree into two trees. Where @code(Max(l) <= k). *)
  40. class procedure Divide(node: TTreapNode; k: T; var l, r: TTreapNode);
  41.  
  42. (* Divides tree into two trees. Where @code(Size(l) = pos). *)
  43. class procedure DivideAt(node: TTreapNode; const pos: SizeUInt;
  44. var l, r: TTreapNode);
  45.  
  46. (* Returns @true if tree rooted at @code(node) is empty, @false otherwise *)
  47. class function IsEmpty(const node: TTreapNode): boolean; inline;
  48.  
  49. (* Insert key @code(k) in tree rooted at @code(node). *)
  50. class procedure Insert(var node: TTreapNode; const k: T); inline;
  51.  
  52. (* Check if tree rooted at @code(root) node contains key @code(k). *)
  53. class function Contains(node: TTreapNode; const k: T): boolean; inline;
  54.  
  55. (* Number of keys less than @code(k) *)
  56. class function BisectLeft(node: TTreapNode; const k: T): SizeUInt;
  57. (* Number of keys less or equal @code(k) *)
  58. class function BisectRight(node: TTreapNode; const k: T): SizeUInt;
  59.  
  60. class function GetPosition(node: TTreapNode; const k: T): SizeUInt;
  61.  
  62. (* @raises(EArgumentException) *)
  63. class function GetAt(node: TTreapNode; pos: SizeUInt): T;
  64.  
  65. (* Removes key from the tree.
  66.   @returns(@true if successful, @false otherwise) *)
  67. class function Remove(var node: TTreapNode; const k: T): boolean;
  68.  
  69. (* Removes key from the given position.
  70.   @returns(key) *)
  71. class function RemoveAt(var node: TTreapNode; const pos: SizeUInt): T;
  72.  
  73. (* Destroy tree. *)
  74. class procedure DestroyTreap(var node: TTreapNode);
  75.  
  76. class function CheckStucture(node: TTreapNode): boolean;
  77. end;
  78.  
  79. //
  80. // TTreapNode Class methods
  81. //
  82. constructor TTreapNode.Create(const k: T);
  83. begin
  84. FKey := k;
  85. FPriority := Random;
  86. FSize := 1;
  87. FLeft := nil;
  88. FRight := nil;
  89. end;
  90.  
  91. destructor TTreapNode.Destroy;
  92. begin
  93. FLeft := nil;
  94. FRight := nil;
  95. inherited;
  96. end;
  97.  
  98. // PASSED
  99. class function TTreapNode.GetSize(const node: TTreapNode): SizeUInt; inline;
  100. begin
  101. if node <> nil then
  102. Exit(node.FSize);
  103. Exit(0);
  104. end;
  105.  
  106. // PASSED
  107. class procedure TTreapNode.UpdateSize(const node: TTreapNode); inline;
  108. begin
  109. if node <> nil then
  110. node.FSize := GetSize(node.FLeft) + GetSize(node.FRight) + 1;
  111. end;
  112.  
  113. class function TTreapNode.IsEmpty(const node: TTreapNode): boolean; inline;
  114. begin
  115. Exit(node = nil);
  116. end;
  117.  
  118. class function TTreapNode.Meld(l, r: TTreapNode): TTreapNode;
  119. begin
  120. if l = nil then
  121. Exit(r);
  122. if r = nil then
  123. Exit(l);
  124. if l.FPriority > r.FPriority then
  125. begin
  126. l.FRight := Meld(l.FRight, r);
  127. Result := l;
  128. end
  129. else
  130. begin
  131. r.FLeft := Meld(l, r.FLeft);
  132. Result := r;
  133. end;
  134. UpdateSize(Result);
  135. end;
  136.  
  137. class procedure TTreapNode.DivideAt(node: TTreapNode; const pos: SizeUInt;
  138. var l, r: TTreapNode);
  139. begin
  140. if node = nil then
  141. begin
  142. l := nil;
  143. r := nil;
  144. Exit
  145. end;
  146. if pos > GetSize(node.FLeft) then
  147. begin
  148. DivideAt(node.FRight, pos - GetSize(node.FLeft) - 1, node.FRight, r);
  149. l := node
  150. end
  151. else
  152. begin
  153. DivideAt(node.FLeft, pos, l, node.FLeft);
  154. r := node
  155. end;
  156. UpdateSize(node)
  157. end;
  158.  
  159. // DivideRight
  160. class procedure TTreapNode.Divide(node: TTreapNode; k: T; var l, r: TTreapNode);
  161. begin
  162. if node = nil then
  163. begin
  164. l := nil;
  165. r := nil;
  166. Exit;
  167. end;
  168. if k < node.FKey then
  169. begin
  170. Divide(node.FLeft, k, l, node.FLeft);
  171. r := node;
  172. end
  173. else
  174. begin
  175. Divide(node.FRight, k, node.FRight, r);
  176. l := node;
  177. end;
  178. UpdateSize(node);
  179. end;
  180.  
  181. class procedure TTreapNode.Insert(var node: TTreapNode; const k: T); inline;
  182. var
  183. l: TTreapNode = nil;
  184. r: TTreapNode = nil;
  185. begin
  186. Divide(node, k, l, r);
  187. node := Meld(l, Meld(TTreapNode.Create(k), r));
  188. end;
  189.  
  190. // PASSED
  191. class function TTreapNode.Contains(node: TTreapNode; const k: T): boolean; inline;
  192. begin
  193. while node <> nil do
  194. begin
  195. if k = node.FKey then
  196. Exit(True);
  197. if k > node.FKey then
  198. node := node.FRight
  199. else
  200. node := node.FLeft;
  201. end;
  202. Exit(False);
  203. end;
  204.  
  205. class function TTreapNode.BisectLeft(node: TTreapNode; const k: T): SizeUInt;
  206. var
  207. pos: SizeUInt = 0;
  208. begin
  209. while node <> nil do
  210. begin
  211. if k > node.FKey then
  212. begin
  213. pos := pos + GetSize(node.FLeft) + 1;
  214. node := node.FRight;
  215. end
  216. else
  217. node := node.FLeft;
  218. end;
  219. Exit(pos);
  220. end;
  221.  
  222. class function TTreapNode.BisectRight(node: TTreapNode; const k: T): SizeUInt;
  223. var
  224. pos: SizeUInt = 0;
  225. begin
  226. while node <> nil do
  227. begin
  228. if k < node.FKey then
  229. node := node.FLeft
  230. else
  231. begin
  232. pos := pos + GetSize(node.FLeft) + 1;
  233. node := node.FRight;
  234. end;
  235. end;
  236. Exit(pos);
  237. end;
  238.  
  239. // PASSED
  240. class function TTreapNode.GetPosition(node: TTreapNode; const k: T): SizeUInt;
  241. var
  242. pos: SizeUInt = 0;
  243. begin
  244. while node <> nil do
  245. begin
  246. if k = node.FKey then
  247. Exit(pos + GetSize(node.FLeft));
  248. if k > node.FKey then
  249. begin
  250. pos := pos + GetSize(node.FLeft) + 1;
  251. node := node.FRight;
  252. end
  253. else
  254. node := node.FLeft;
  255. end;
  256. raise Exception.Create('No such key');
  257. end;
  258.  
  259. // PASSED
  260. class function TTreapNode.GetAt(node: TTreapNode; pos: SizeUInt): T;
  261. var
  262. lsize: SizeUInt = 0;
  263. begin
  264. if (node = nil) or (pos > GetSize(node) - 1) then
  265. raise EArgumentException.Create('Set is empty or position is out of range.');
  266. while node <> nil do
  267. begin
  268. lsize := GetSize(node.FLeft);
  269. if pos = lsize then
  270. Exit(node.FKey);
  271. if pos > lsize then
  272. begin
  273. node := node.FRight;
  274. pos := pos - lsize - 1;
  275. end
  276. else
  277. node := node.FLeft;
  278. end;
  279. raise Exception.Create('Unreachable point.');
  280. end;
  281.  
  282. class function TTreapNode.Remove(var node: TTreapNode; const k: T): boolean;
  283. var
  284. n: TTreapNode;
  285. begin
  286. Result := False;
  287. if node <> nil then
  288. begin
  289. if k = node.FKey then
  290. begin
  291. n := node;
  292. node := Meld(node.FLeft, node.FRight);
  293. FreeAndNil(n);
  294. Exit(True);
  295. end;
  296. if k > node.FKey then
  297. Result := Remove(node.FRight, k)
  298. else
  299. Result := Remove(node.FLeft, k);
  300. if Result then
  301. UpdateSize(node);
  302. end;
  303. end;
  304.  
  305. // RWRT
  306. class function TTreapNode.RemoveAt(var node: TTreapNode; const pos: SizeUInt): T;
  307. var
  308. n: TTreapNode;
  309. begin
  310. if (node = nil) or (pos > GetSize(node) - 1) then
  311. raise EArgumentException.Create('Set is empty or position is out of range.');
  312. if pos = GetSize(node.FLeft) then
  313. begin
  314. Result := node.FKey;
  315. n := node;
  316. node := Meld(node.FLeft, node.FRight);
  317. FreeAndNil(n);
  318. Exit;
  319. end;
  320. if pos > GetSize(node.FLeft) then
  321. Result := RemoveAt(node.FRight, pos - GetSize(node.FLeft) - 1)
  322. else
  323. Result := RemoveAt(node.FLeft, pos);
  324. UpdateSize(node);
  325. end;
  326.  
  327. class procedure TTreapNode.DestroyTreap(var node: TTreapNode);
  328. begin
  329. if node <> nil then
  330. begin
  331. DestroyTreap(node.FLeft);
  332. DestroyTreap(node.FRight);
  333. FreeAndNil(node);
  334. end;
  335. end;
  336.  
  337. class function TTreapNode.CheckStucture(node: TTreapNode): boolean;
  338. begin
  339. Result := True;
  340. if node = nil then
  341. Exit(Result);
  342. with node do
  343. begin
  344. Result := Result and CheckStucture(node.FLeft);
  345. Result := Result and CheckStucture(node.FRight);
  346. Result := Result and (GetSize(node) = GetSize(node.FLeft) +
  347. GetSize(node.FRight) + 1);
  348. if node.FLeft <> nil then
  349. begin
  350. Result := Result and (node.FPriority >= node.FLeft.FPriority);
  351. Result := Result and ((node.FKey > node.FLeft.FKey) or
  352. (node.FKey = node.FLeft.FKey));
  353. end;
  354. if node.FRight <> nil then
  355. begin
  356. Result := Result and (node.FPriority >= node.FRight.FPriority);
  357. Result := Result and (node.FKey < node.FRight.FKey);
  358. end;
  359. end;
  360. end;
  361.  
  362. type
  363. TInt64TreapNode = specialize TTreapNode<Int64>;
  364.  
  365. var
  366. ra: TInt64TreapNode = nil;
  367. i: longint;
  368.  
  369. begin
  370. Randomize;
  371. for i:= 1 to 1600000 do
  372. begin
  373. TInt64TreapNode.Insert(ra, Random(9223372036854775807));
  374. end;
  375. WriteLn(TInt64TreapNode.GetSize(ra));
  376. end.
  377. (*
  378. 100000 - 0.08s
  379. 200000 - 0.19s
  380. 400000 - 0.42s
  381. 800000 - 1.06s
  382. 1600000 - 2.58s
  383. *)
Success #stdin #stdout 2.59s 150784KB
stdin
Standard input is empty
stdout
1600000