提出 #7632026


ソースコード 拡げる

module Program

// -----------------------------------------------
// Binary trees
// -----------------------------------------------

[<RequireQualifiedAccess>]
type Tree<'a> =
  | Leaf
    of 'a
  | Node
    of Tree<'a> * Tree<'a>

let inline treeNewLeaf item =
  Tree.Leaf item

let inline treeNewNode (left: Tree<_>) (right: Tree<_>) =
  Tree.Node (left, right)

let treeGet w index (node: Tree<_>) =
  // assert (0 <= index && index < w)

  let rec go w index node =
    match node with
    | Tree.Leaf item ->
      // assert (w = 1 && index = 0)
      item

    | Tree.Node (left, right) ->
      let v = w / 2
      if index < v then
        go v index left
      else
        go v (index - v) right

  go w index node

let treeSet w index newItem (node: Tree<_>) =
  // assert (0 <= index && index < w)

  let rec go w index node =
    match node with
    | Tree.Leaf _ ->
      // assert (w = 1 && index = 0)
      treeNewLeaf newItem

    | Tree.Node (left, right) ->
      let v = w / 2
      if index < v then
        let left = go v index left
        treeNewNode left right
      else
        let right = go v (index - v) right
        treeNewNode left right

  go w index node

// -----------------------------------------------
// Zero-less binary digits
// -----------------------------------------------

// [<Struct>]
[<RequireQualifiedAccess>]
type Digit<'a> =
  | One
    of Tree<'a>
  | Two
    of Tree<'a> * Tree<'a>

let inline digitNewOne (node: Tree<_>) =
  Digit.One node

let inline digitNewTwo (left: Tree<_>) (right: Tree<_>) =
  Digit.Two (left, right)

// -----------------------------------------------
// Random access lists
// -----------------------------------------------

let ralNewEmpty defaultItem =
  0, [], defaultItem

let ralIsEmpty ral =
  let _, digits, _ = ral
  List.isEmpty digits

let ralToLength ral =
  let len, _, _ = ral
  len

let ralPush item ral =
  let len, digits, defaultItem = ral
  // assert ([item; defaultItem] |> List.isEmpty |> not)

  let rec go w t ds =
    match ds with
    | [] ->
      [digitNewOne t]

    | Digit.One u :: ds ->
      digitNewTwo t u :: ds

    | Digit.Two (left, right) :: ds ->
      let u = treeNewNode left right
      digitNewOne t :: go (w * 2) u ds

  let digits = go 1 (treeNewLeaf item) digits
  len + 1, digits, defaultItem

let ralGet index ral =
  let len, digits, defaultItem = ral
  // assert (0 <= index && index < len)

  let rec go w index digits =
    match digits with
    | [] ->
      // assert false
      defaultItem

    | d :: ds ->
      match d with
      | Digit.One node ->
        if index < w then
          treeGet w index node
        else
          go (w * 2) (index - w) ds

      | Digit.Two (left, right) ->
        if index < w then
          treeGet w index left
        else if index < w * 2 then
          treeGet w (index - w) right
        else
          go (w * 2) (index - w * 2) ds

  let index = len - index - 1
  go 1 index digits

let ralSet index newItem ral =
  let len, digits, defaultItem = ral
  // assert (0 <= index && index < len)
  // assert ([newItem; defaultItem] |> List.isEmpty |> not)

  let rec go w index digits =
    match digits with
    | [] ->
      // assert false
      digits

    | d :: ds ->
      match d with
      | Digit.One node ->
        if index < w then
          let t = treeSet w index newItem node
          digitNewOne t :: ds
        else
          d :: go (w * 2) (index - w) ds

      | Digit.Two (left, right) ->
        if index < w then
          let left = treeSet w index newItem left
          digitNewTwo left right :: ds
        else if index < w * 2 then
          let right = treeSet w (index - w) newItem right
          digitNewTwo left right :: ds
        else
          d :: go (w * 2) (index - w * 2) ds

  let index = len - index - 1
  let digits = go 1 index digits
  len, digits, defaultItem

let ralReplicate len item =
  // assert (len >= 0)

  if len = 0 then
    ralNewEmpty item
  else

  let treeReplicate w item =
    let rec go w =
      if w = 1 then
        treeNewLeaf item
      else
        let t = go (w / 2)
        treeNewNode t t
    go w

  let rec go w n =
    let t = treeReplicate w item

    if n = 0 then
      []
    else if n % (w * 2) = 0 then
      digitNewTwo t t :: go (w * 2) (n - w * 2)
    else
      // assert ((n - w) % (w * 2) = 0)
      digitNewOne t :: go (w * 2) (n - w)

  let digits = go 1 len
  len, digits, item

// -----------------------------------------------
// ABC 140 E
// -----------------------------------------------

let abc140eSolve n (perm: int[]) =
  let prev, next =
    let rec go i prev next =
      if i > n then
        prev, next
      else
        let prev = ralPush i prev
        let next = ralPush i next
        go (i + 1) prev next

    let prev = ralNewEmpty 0 |> ralPush 0 |> ralPush 0
    let next = ralNewEmpty 0
    let prev, next = go 1 prev next
    let next = next |> ralPush (n + 1) |> ralPush (n + 1)
    prev, next

  // inverse of perm
  let pos =
    let rec go i pos =
      if i = n then
        pos
      else
        go (i + 1) (ralSet (perm.[i] - 1) (i + 1) pos)

    let pos = ralReplicate n 0
    go 0 pos

  let rec go sum prev next p =
    if p = n then
      sum
    else
      let i = ralGet p pos

      let x = ralGet i prev
      let w = ralGet x prev
      // assert (w <= x && x < i)

      let y = ralGet i next
      let z = ralGet y next
      // assert (i < y && y <= z)

      let count = (x - w) * (y - i) + (i - x) * (z - y)
      let sum = sum + int64 count * int64 (p + 1)

      let prev = ralSet y x prev
      let next = ralSet x y next
      go sum prev next (p + 1)

  go 0L prev next 0

[<EntryPoint>]
let main _ =
  let n = stdin.ReadLine() |> int
  let perm = stdin.ReadLine().Split(' ') |> Array.map int
  let m = abc140eSolve n perm
  printfn "%s" (string m)
  0

提出情報

提出日時
問題 E - Second Sum
ユーザ vain0
言語 F# (Mono 4.0)
得点 500
コード長 6143 Byte
結果 AC
実行時間 783 ms
メモリ 67268 KiB

ジャッジ結果

セット名 Sample All
得点 / 配点 0 / 0 500 / 500
結果
AC × 3
AC × 22
セット名 テストケース
Sample 00-sample-01.txt, 00-sample-02.txt, 00-sample-03.txt
All 00-sample-01.txt, 00-sample-02.txt, 00-sample-03.txt, 01-small-01.txt, 01-small-02.txt, 01-small-03.txt, 01-small-04.txt, 01-small-05.txt, 02-large-01.txt, 02-large-02.txt, 02-large-03.txt, 02-large-04.txt, 02-large-05.txt, 03-max-01.txt, 03-max-02.txt, 04-min-01.txt, 05-sorted-01.txt, 05-sorted-02.txt, 06-almost-sorted-01.txt, 06-almost-sorted-02.txt, 06-almost-sorted-03.txt, 06-almost-sorted-04.txt
ケース名 結果 実行時間 メモリ
00-sample-01.txt AC 46 ms 12124 KiB
00-sample-02.txt AC 46 ms 12124 KiB
00-sample-03.txt AC 46 ms 14172 KiB
01-small-01.txt AC 46 ms 14172 KiB
01-small-02.txt AC 46 ms 12124 KiB
01-small-03.txt AC 46 ms 12124 KiB
01-small-04.txt AC 46 ms 14172 KiB
01-small-05.txt AC 45 ms 10076 KiB
02-large-01.txt AC 676 ms 67268 KiB
02-large-02.txt AC 411 ms 50996 KiB
02-large-03.txt AC 706 ms 65320 KiB
02-large-04.txt AC 734 ms 65828 KiB
02-large-05.txt AC 445 ms 50684 KiB
03-max-01.txt AC 764 ms 66152 KiB
03-max-02.txt AC 783 ms 65640 KiB
04-min-01.txt AC 46 ms 10192 KiB
05-sorted-01.txt AC 473 ms 43156 KiB
05-sorted-02.txt AC 397 ms 47584 KiB
06-almost-sorted-01.txt AC 456 ms 42024 KiB
06-almost-sorted-02.txt AC 370 ms 41608 KiB
06-almost-sorted-03.txt AC 468 ms 43156 KiB
06-almost-sorted-04.txt AC 365 ms 45328 KiB