#=== Template_Base =========================== {{{

import strutils, sequtils, math, algorithm, nre, tables, macros
when (not (NimMajor <= 0)) or NimMinor >= 19:
  import sugar
else:
  import future

# type
#   si = seq[int]
#   ssi = seq[seq[int]]
#   sf = seq[float]
#   ssf = seq[seq[float]]

# proc r(): string = stdin.readLine
# proc ri(): int = r().parseInt
# proc rsi(): seq[int] = r().split.map(parseInt)
# proc rf(): float = r().parseFloat
# proc rsf(): seq[float] = r().split.map(parseFloat)
# proc rn(n: int): seq[string] =
#   result = @[]
#   for i in 1..n:
#     result.add(r())
# proc rin(n: int): seq[int] =
#   result = @[]
#   for i in 1..n:
#     result.add(ri())
# proc rsin(n: int): seq[seq[int]] =
#   result = @[]
#   for i in 1..n:
#     result.add(rsi())
iterator range(x, y: int): int {.inline.} =
  var res = x
  while res < y:
    yield res
    inc(res)
iterator range(x: int): int {.inline.} =
  var res = 0
  while res < x:
    yield res
    inc(res)
proc range(x, y: int): seq[int] {.inline.} =
  toSeq(x..y-1)
proc range(x: int): seq[int] {.inline.} =
  toSeq(0..x-1)
proc discardableId[T](x: T): T {.discardable.} =
  return x
template `:=`(x, y: untyped): untyped =
  when defined(x):
    (x = y; discardableId(x))
  else:
    (var x = y; discardableId(x))
when NimMajor <= 0 and NimMinor <= 17:
  proc count[T](co: openArray[T]; obj: T): int =
    for itm in items(co):
      if itm == obj:
        inc result
proc divmod(x, y: SomeInteger): (int, int) =
  (x div y, x mod y)
proc `min=`[T](x: var T; y: T): bool {.discardable.} =
  if x > y:
    x = y
    return true
  else:
    return false
proc `max=`[T](x: var T; y: T): bool {.discardable.} =
  if x < y:
    x = y
    return true
  else:
    return false

when NimMajor <= 0 and NimMinor <= 17:
  iterator pairs(n: NimNode): (int, NimNode) {.inline.} =
    for i in 0 ..< n.len:
      yield (i, n[i])

when NimMajor <= 0 and NimMinor <= 18:
  macro parseInnerType(x: NimNode): untyped =
    newIdentNode("parse" & x[1][1].repr)
else:
  macro parseInnerType(x: typedesc): untyped =
    newIdentNode("parse" & x.getType[1][1].repr)

macro inputAsTuple(ty: untyped): untyped =
  result = nnkStmtListExpr.newTree()
  t := genSym()
  result.add quote do: (let `t` = stdin.readLine.split)
  p := nnkPar.newTree()
  for i, typ in ty.pairs:
    if typ.repr == "string":
      p.add quote do: `t`[`i`]
    else:
      parsefn := newIdentNode("parse" & typ.repr)
      p.add quote do: `t`[`i`].`parsefn`
  result.add p

template inputAsType(ty: static[typedesc]): auto =
  when ty is seq:
    when ty is seq[string]:
      stdin.readLine.split
    else:
      when NimMajor <= 0 and NimMinor <= 18:
        stdin.readLine.split.map(parseInnerType(ty.getType))
      else:
        stdin.readLine.split.map(parseInnerType(ty))
  elif ty is string:
    stdin.readLine
  elif ty is tuple:
    inputAsTuple(ty)
  else:
    stdin.readLine.`parse ty`

macro input(query: untyped): untyped =
  doAssert query.kind == nnkStmtList
  result = nnkStmtList.newTree()
  letSect := nnkLetSection.newTree()
  for defs in query:
    if defs[0].kind == nnkIdent:
      tmp := nnkIdentDefs.newTree(defs[0], newEmptyNode())
      typ := defs[1][0]
      var val: NimNode
      if typ.len <= 2:
        val = quote do: inputAsType(`typ`)
      else:
        op := typ[2]
        typ.del(2, 1)
        val = quote do: inputAsType(`typ`).mapIt(`op`)
      if defs[1].len > 1:
        op := defs[1][1]
        it := ident"it"
        tmp.add quote do: (var `it` = `val`; `op`)
      else:
        tmp.add val
      letSect.add tmp
    elif defs[0].kind == nnkPar:
      vt := nnkVarTuple.newTree()
      for id in defs[0]:
        vt.add id
      vt.add newEmptyNode()
      sle := nnkStmtListExpr.newTree()
      t := genSym()
      sle.add quote do: (let `t` = stdin.readLine.split)
      p := nnkPar.newTree()
      if defs[1][0].kind == nnkPar:
        for i, typ in defs[1][0].pairs:
          if typ.repr == "string":
            p.add quote do: `t`[`i`]
          else:
            parsefn := newIdentNode("parse" & typ.repr)
            p.add quote do: `t`[`i`].`parsefn`
      else:
        typ := defs[1][0]
        if typ.repr == "string":
          for i in 0..<defs[0].len:
            p.add quote do: `t`[`i`]
        else:
          parsefn := newIdentNode("parse" & typ.repr)
          for i in 0..<defs[0].len:
            p.add quote do: `t`[`i`].`parsefn`
      sle.add p
      vt.add sle
      letSect.add vt
    elif defs[0].kind == nnkBracketExpr:
      ids := nnkIdentDefs.newTree(defs[0][0], newEmptyNode())
      cnt := defs[0][1]
      typ := defs[1][0]
      var val: NimNode
      if typ.len <= 2:
        val = quote do: inputAsType(`typ`)
      elif typ.len > 2:
        op := typ[2]
        typ.del(2, 1)
        val = quote do: inputAsType(`typ`).mapIt(`op`)
      if defs[1].len > 1:
        op := defs[1][1]
        it := ident"it"
        ids.add (quote do: newSeqWith(`cnt`, (var `it` = `val`; `op`)))
      else:
        ids.add (quote do: newSeqWith(`cnt`, `val`))
      letSect.add ids
  result.add letSect

#=== Template_Base =========================== }}}

input:
  N: int
  A[N]: int

let maxVal = A.max

for i, a in A:
  if a == maxVal:
    var tmp = A
    tmp[i] = int.low
    echo tmp.max
  else:
    echo maxVal
