結果
問題 | No.738 平らな農地 |
ユーザー |
![]() |
提出日時 | 2019-04-18 12:40:23 |
言語 | Nim (2.2.0) |
結果 |
AC
|
実行時間 | 507 ms / 2,000 ms |
コード長 | 3,150 bytes |
コンパイル時間 | 3,619 ms |
コンパイル使用メモリ | 66,664 KB |
実行使用メモリ | 18,176 KB |
最終ジャッジ日時 | 2024-07-01 23:10:58 |
合計ジャッジ時間 | 25,515 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 5 |
other | AC * 87 |
コンパイルメッセージ
/home/judge/data/code/Main.nim(1, 28) Warning: use `std/random` instead; mersenne is deprecated [Deprecated]
ソースコード
import strutils, sequtils, mersennevar mt = newMersenneTwister(0)type Node = ref objectval: int64priority: intsize: intsum: int64left, right: Nodeproc newNode(val: int64): Node =let node = new Nodenode.val = valnode.priority = mt.getNum().intnode.size = 1node.sum = valreturn nodetype Pair = Nodeproc makePair(left, right: Node): Pair =let pair = new Pairpair.left = leftpair.right = rightreturn pairproc size(root: Node): int =return if root == nil: 0 else: root.sizeproc sum(root: Node): int64 =return if root == nil: 0.int64 else: root.sumproc update(node: Node): Node =node.size = 1 + size(node.left) + size(node.right)node.sum = node.val + sum(node.left) + sum(node.right)return node# max(left) <= min(right) じゃないとダメ?proc merge(left, right: Node): Node =if left == nil:return rightelif right == nil:return leftif left.priority > right.priority:left.right = merge(left.right, right)return update(left)else:right.left = merge(left, right.left)return update(right)# k 個と size(root)-k 個に分けるproc split(root: Node, k: int): Pair =if root == nil:return makePair(root, root)if k <= size(root.left):let pair = split(root.left, k)root.left = pair.rightreturn makePair(pair.left, update(root))else:let pair = split(root.right, k - size(root.left) - 1)root.right = pair.leftreturn makePair(update(root), pair.right)proc countLess(root: Node, x: int64): int =if root == nil:return 0if root.val < x:return size(root.left) + 1 + countLess(root.right, x)else:return countLess(root.left, x) # root.val==x の分はカウントしないproc insert(root: Node, x: int64): Node =letk = root.countLess(x)pair = split(root, k) # pair.left には x 未満しかないreturn merge(merge(pair.left, newNode(x)), pair.right)proc erase(root: Node, x: int64): Node =letk = root.countLess(x)pair = split(root, k)if pair.right != nil:let pp = split(pair.right, 1) # pp.left は x のみreturn merge(pair.left, pp.right)else: # x が存在しないreturn merge(pair.left, pair.right)proc getKth(root: Node, k: int): Node =if root == nil or size(root) < k:return nilif size(root.left) + 1 == k:return rootelif size(root.left) >= k:return getKth(root.left, k)else:return getKth(root.right, k - size(root.left) - 1)proc main() =letnk = stdin.readLine.strip.split.map(parseInt)(n, k) = (nk[0], nk[1])a = stdin.readLine.strip.split.map(parseBiggestInt)varroot: Node = nilans = int64.highfor i in 0..<n:root = root.insert(a[i])if i >= k:root = root.erase(a[i - k])if i + 1 >= k:letkth = root.getKth((k + 1) div 2)pair = root.split((k + 1) div 2)var cost: int64 = 0cost += kth.val * size(pair.left) - sum(pair.left)cost += sum(pair.right) - kth.val * size(pair.right)if cost < ans:ans = costroot = merge(pair.left, pair.right)echo ansmain()