ABC 136 F. Enclosed Points

https://atcoder.jp/contests/abc136/tasks/abc136_f

I solved problems with F# because I don't want to use C++. Although I prefer to OCaml, I gave up it due to 64bit integers. I use verbose F# because in off-side rule we can't restore indents when carelessly erase them. OCaml is almost as fast as C++, where F# is a little slow regarding IO, so we should prepare own IO functions. Unbuffered IO is really slow.

UPD: I thought F# is available in Codeforces, but it is unavailable now. OCaml is not suitable for contest because OCaml doesn't have binary operators for 64bit integers. In 64bit platform, int has 64 bit precision, but Codeforces is now 32bit.

UPD: The following source code realize Int64 arithmetics. I want to use https://caml.inria.fr/pub/docs/manual-ocaml/manual042.html, but no contests support now. I want to replace all int with Int64, but some functions in the standard library takes int, so I can't.

open Scanf
open Printf

module L = struct
  open Int64
  let ( + ), ( - ), ( * ), ( / ), ( % ), ( ~- ) = add, sub, mul, div, rem, neg
end
let ( ~~ ) = Int64.of_int
let ( !! ) = Int64.to_int

let readint () = scanf " %d" (fun x -> x)
let readint64 () = scanf " %Ld" (fun x -> x)

module M = struct
  let md = 7L
  let ( + ) x y = let z = Int64.add x y in if z < md then z else Int64.sub z md
  let ( - ) x y = let z = Int64.sub x y in if z >= 0L then z else Int64.add z md
  let ( * ) x y = Int64.rem (Int64.mul x y) md
end

type bit = { dat : int64 array }

module BIT = struct
  let make (n : int) : bit = { dat=Array.make (n + 1) 0L }
  let update (bit : bit) (k : int) (v : int64) =
    let { dat } = bit in
    let i = ref (k + 1) in
    while !i < Array.length dat do
      dat.(!i) <- L.(dat.(!i) + v);
      i := !i + (!i land -(!i))
    done
  let query (bit : bit) (k : int) : int64 =
    let { dat } = bit in
    let i = ref k in
    let ans = ref 0L in
    while !i > 0 do
      ans := L.(!ans + dat.(!i));
      i := !i - (!i land -(!i))
    done;
    !ans
end

let () =
  assert (L.(2L + 3L) = 5L);
  assert (L.(2L - 3L) = -1L);
  assert (L.(2L * 3L) = 6L);
  assert (L.(2L / 3L) = 0L);
  assert (L.(2L % 3L) = 2L);
  assert (L.(min 2L 3L) = 2L);
  assert (M.(4L + 5L) = 2L);
  assert (M.(4L - 5L) = 6L);
  assert (M.(4L * 5L) = 6L);
  let bit = BIT.make 10 in
  for i = 0 to 9 do
    BIT.update bit i ~~(i+1)
  done;
  for i = 0 to 10 do
    let i = ~~i in
    assert (BIT.query bit !!i = L.(i * (i + 1L) / 2L))
  done;
  try (BIT.query bit (-1) |> ignore; failwith "") with _ -> ();
  try (BIT.query bit 11 |> ignore; failwith "") with _ -> ();

I used the following template. I'll omit the template.

#nowarn "62"
#light "off"
open System;;
open System.IO;;

let reader = new StreamReader(new BufferedStream(Console.OpenStandardInput ()));;
let writer = new StreamWriter(new BufferedStream(Console.OpenStandardOutput ()));;

let skipSpaces () = while reader.Peek () <= int ' ' do reader.Read () |> ignore done;;
let read f = skipSpaces (); [|while reader.Peek () > int ' ' do yield char (reader.Read ()) done |] |> System.String |> f;;
let readint () = skipSpaces (); let s = if reader.Peek() = int '-' then (ignore (reader.Read()); -1) else 1 in let mutable ans = 0 in while reader.Peek () > int ' ' do ans <- ans * 10 + (reader.Read () - int '0'); done; s * ans;;
let write (s : string) = writer.Write s;;
let writeln (s : string) = writer.WriteLine s;;

(* Write code here *)

reader.Close();;
writer.Close();;

Problem A

let a, b, c = readint (), readint (), readint();;
c - min (a - b) c |> printfn "%d";;

Problem B

I wrote keta function. string >> String.length may be simpler than it.

let rec keta n = if n = 0 then 0 else 1 + keta (n / 10);;
let N = readint ();;
{1..N} |> Seq.filter (fun x -> keta x % 2 = 1) |> Seq.length |> printfn "%d";

Problem C

As looking at elements from left to right, greedily subtract one from each element if we can.

A.[0] <- A.[0] - 1;;
let mutable ans = true;;

for i in 1..N-1 do
  if A.[i-1] > A.[i] then
    ans <- false
  elif A.[i-1] < A.[i] then
    A.[i] <- A.[i] - 1
done;;

(if ans then "Yes" else "No") |> printfn "%s";;

Problem D

It seems that doubling solution is easy to write than I thought. I wrote two pointers.

let S = read string;;
let N = S.Length;;

let mutable i = 0;;
let ans = Array.create N 0;;

while i < N do
  let j = i in
  i <- {i..N} |> Seq.find (fun i -> i = N || S.[i] <> 'R');
  let k = i in
  i <- {i..N} |> Seq.find (fun i -> i = N || S.[i] <> 'L');
  let a, b = k - j, i - k in
  ans.[k-1] <- ((a + 1) / 2 + b / 2);
  ans.[k] <- (a / 2 + (b + 1) / 2);
done;;

ans |> Array.map string |> String.concat " " |> writeln;;

Problem E

Once we notice that the sum doesn't change, we almost have solved this problem. That's a lie. Greedy part is not trivial for me.

let divisors x = Seq.initInfinite ((+) 1) |> Seq.takeWhile (fun i -> i * i <= x) |> Seq.filter (fun i -> x % i = 0) |> Seq.collect (fun i -> seq [i; x / i]);;

let N, K = readint (), readint ();;
let A = Array.init N (ignore >> readint);;

let f d =
  let x = Array.init N (fun i -> A.[i] % d) |> Array.sort in
  let mutable i = 0 in
  let mutable j = N - 1 in
  let mutable souwa = 0 in
  while i < j do
    let tukau = min x.[i] (d - x.[j]) in
    souwa <- souwa + tukau;
    x.[i] <- x.[i] - tukau;
    x.[j] <- x.[j] + tukau;
    if x.[i] = 0 then i <- i + 1;
    if x.[j] = d then j <- j - 1;
  done;
  souwa <= K;;

divisors (Array.sum A) |> Seq.filter f |> Seq.max |> printf "%d";;
Problem F

If we can notice that x[i]!=x[j] and y[i]!=y[j], this problem become a little easier. However, we can solve this problem without this constraint (My first solution is so).
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>] is too long.

let MOD = 998244353;;
type Mint = Mint of int
  with
    static member (+) (Mint x, Mint y) = Mint (let z = x + y in if z < MOD then z else z - MOD)
    static member (-) (Mint x, Mint y) = Mint (let z = x - y in if z >= 0 then z else z + MOD)
    static member (*) (Mint x, Mint y) = int64 x * int64 y % int64 MOD |> int |> Mint
    override this.ToString() = match this with Mint x -> x.ToString()
  end;;

type BIT = { dat : int [] }
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module BIT =
  begin
    let create n : BIT = { dat = Array.create (n + 1) 0 }
    let update ({dat=dat} : BIT) (k : int) (v : int) =
      let mutable i = k + 1 in
      while i < Array.length dat do dat.[i] <- dat.[i] + v; i <- i + (i &&& -i) done
    let query ({dat=dat} : BIT) (k : int) : int =
      let mutable i = k in
      let mutable ans = 0 in
      while i > 0 do ans <- ans + dat.[i]; i <- i - (i &&& -i) done;
      ans
  end;;

let N = readint ();;
let X, Y = Array.init N (fun _ -> readint (), readint ()) |> Array.sort |> Array.unzip;;
let YD = Y |> Array.distinct |> Array.sort |> Array.mapi (fun i x -> x, i) |> Map.ofArray;;
for i in 0..N-1 do Y.[i] <- YD.[Y.[i]] done;;
let L = BIT.create YD.Count;;
let R = BIT.create YD.Count;;
for y in Y do BIT.update R y 1 done;;

let two = Array.replicate N (Mint 2) |> Array.scan (*) (Mint 1);;

let mutable ans = two.[N] * (Mint N);;
for i in 0..N-1 do
  BIT.update R Y.[i] (-1);
  let d = BIT.query L Y.[i] in
  let c = BIT.query R Y.[i] in
  let a = i - d in
  let b = (N-1-i-c) in
  [Mint 1;
  two.[a] - Mint 1; two.[b] - Mint 1; two.[c] - Mint 1; two.[d] - Mint 1;
  (two.[a] - Mint 1) * (two.[b] - Mint 1);
  (two.[b] - Mint 1) * (two.[c] - Mint 1);
  (two.[c] - Mint 1) * (two.[d] - Mint 1);
  (two.[d] - Mint 1) * (two.[a] - Mint 1)] |> List.iter (fun x -> ans <- ans - x);
  BIT.update L Y.[i] 1;
done;;
printfn "%O" ans;;