{.push hints:off.}
import algorithm, hashes, macros, math, sequtils, sets, strutils, tables, times, unicode
when NimMajor <= 0 and NimMinor <= 17: import future else: import sugar
when NimMajor <= 0 and NimMinor <= 17: import queues

macro unpack(rhs: seq, cnt: static[int]): auto =
  let t = genSym(); result = quote do:(let `t` = `rhs`;())
  when NimMajor <= 0 and NimMinor <= 17:
    for i in 0..<cnt: result[0][1].add(quote do:`t`[`i`])
  else:
    for i in 0..<cnt: result[1].add(quote do:`t`[`i`])
 
template input(T: typedesc, cnt: Natural = 1): untyped =
  let line = stdin.readLine.split(" ")
  when T is int:         line.map(parseInt).unpack(cnt)
  elif T is float:       line.map(parseFloat).unpack(cnt)
  elif T is string:      line.unpack(cnt)
  elif T is char:        line.mapIt(it[0]).unpack(cnt)
  elif T is seq[int]:    line.map(parseInt)
  elif T is seq[float]:  line.map(parseFloat)
  elif T is seq[string]: line
  elif T is seq[char]:   line.mapIt(it[0])

proc floorMod*[T: SomeNumber](x, y: T): T =
  result = x mod y
  if (result > 0 and y < 0) or (result < 0 and y > 0): result += y

proc `%`(n,m:int):int = floorMod(n,m)
proc `%=`(n: var int, m: int)  = n = floorMod(n,m)
proc `//=`(n: var int, m: int) = n = n div m
proc `<<=`(n: var int, m: int) = n = n shl m
proc `>>=`(n: var int, m: int) = n = n shr m
proc `:<=`[T](n: var T, m: T):bool {.discardable.}=
  result = n > m
  if result:
    n = m
proc `:>=`[T](n: var T, m: T):bool {.discardable.}=
  result = n < m
  if result:
    n = m
proc newSeq2[T](n1, n2: Natural): seq[seq[T]] = newSeqWith(n1, newSeq[T](n2))
proc newSeq3[T](n1, n2, n3: Natural): seq[seq[seq[T]]] = newSeqWith(n1, newSeqWith(n2, newSeq[T](n3)))
proc spacingStr(things: varargs[string,`$`]):string =
  result = ""
  for thing in things:
    result &= thing
    result &= " "
  result &= "\n"
proc spacingStr[T](things: seq[T]):string =
  result = ""
  for thing in things:
    result &= $thing
    result &= " "
  result &= "\n"
proc spacingStr[T](things: seq[seq[T]]):string =
  result = ""
  for thing in things:
    result &= spacingStr(thing)
proc spacingStrPlusOne(things: varargs[int]):string =
  result = ""
  for thing in things:
    result &= $(thing+1)
    result &= " "
  result &= "\n"
proc spacingStrPlusOne[T](things: seq[T]):string =
  result = ""
  for thing in things:
    result &= $(thing+1)
    result &= " "
  result &= "\n"
proc spacingStrPlusOne[T](things: seq[seq[T]]):string =
  result = ""
  for thing in things:
    result &= spacingStrPlusOne(thing)
proc spacingEcho(things: varargs[string,`$`]) = stdout.write(spacingStr(things))
proc spacingEcho[T](things: seq[T]) = stdout.write(spacingStr(things))
proc spacingEcho[T](things: seq[seq[T]]) = stdout.write(spacingStr(things))
proc spacingEchoPlusOne(things: varargs[int]) = stdout.write(spacingStrPlusOne(things))
proc spacingEchoPlusOne(things: seq[int]) = stdout.write(spacingStrPlusOne(things))
proc spacingEchoPlusOne(things: seq[seq[int]]) = stdout.write(spacingStrPlusOne(things))
template myDump*(things: varargs[string,`$`]) =
  when NimMajor > 0 or NimMinor > 17:
    let sr = spacingStr(things)
    let line = instantiationInfo().line
    let lineName = "LINE" & '0'.repeat(4-($line).len) & ($line) & "...>  "
    stdout.write(lineName & sr)
template myDump*[T](things: seq[T]) =
  when NimMajor > 0 or NimMinor > 17:
    let sr = spacingStr(things)
    let line = instantiationInfo().line
    let lineName = "LINE" & '0'.repeat(4-($line).len) & ($line) & "...>  "
    stdout.write(lineName & sr)
template myDump*[T](things: seq[seq[T]]) =
  when NimMajor > 0 or NimMinor > 17:
    let sr = spacingStr(things)
    let line = instantiationInfo().line
    let lineName = "LINE" & '0'.repeat(4-($line).len) & ($line) & "...v\n"
    stdout.write(lineName & sr)
iterator items(n:int):int = 
  for i in 0..<n:
    yield i
{.pop.}

# -------------------------------------------------- #
#
#            Nim's Runtime Library
#        (c) Copyright 2012 Andreas Rumpf
#


import math, typetraits

type
  Deque*[T] = object
    ## A double-ended queue backed with a ringed seq buffer.
    data: seq[T]
    head, tail, count, mask: int

proc initDeque*[T](initialSize: int = 4): Deque[T] =
  ## Create a new deque.
  ## Optionally, the initial capacity can be reserved via `initialSize` as a
  ## performance optimization. The length of a newly created deque will still
  ## be 0.
  ##
  ## `initialSize` needs to be a power of two. If you need to accept runtime
  ## values for this you could use the ``nextPowerOfTwo`` proc from the
  ## `math <math.html>`_ module.
  assert isPowerOfTwo(initialSize)
  result.mask = initialSize-1
  newSeq(result.data, initialSize)

proc len*[T](deq: Deque[T]): int {.inline.} =
  ## Return the number of elements of `deq`.
  result = deq.count

template emptyCheck(deq) =
  # Bounds check for the regular deque access.
  when compileOption("boundChecks"):
    if unlikely(deq.count < 1):
      raise newException(IndexError, "Empty deque.")

template xBoundsCheck(deq, i) =
  # Bounds check for the array like accesses.
  when compileOption("boundChecks"):  # d:release should disable this.
    if unlikely(i >= deq.count):  # x < deq.low is taken care by the Natural parameter
      raise newException(IndexError,
                         "Out of bounds: " & $i & " > " & $(deq.count - 1))

proc `[]`*[T](deq: Deque[T], i: Natural) : T {.inline.} =
  ## Access the i-th element of `deq` by order from first to last.
  ## deq[0] is the first, deq[^1] is the last.
  xBoundsCheck(deq, i)
  return deq.data[(deq.head + i) and deq.mask]

proc `[]`*[T](deq: var Deque[T], i: Natural): var T {.inline.} =
  ## Access the i-th element of `deq` and returns a mutable
  ## reference to it.
  xBoundsCheck(deq, i)
  return deq.data[(deq.head + i) and deq.mask]

proc `[]=`* [T] (deq: var Deque[T], i: Natural, val : T) {.inline.} =
  ## Change the i-th element of `deq`.
  xBoundsCheck(deq, i)
  deq.data[(deq.head + i) and deq.mask] = val

iterator items*[T](deq: Deque[T]): T =
  ## Yield every element of `deq`.
  var i = deq.head
  for c in 0 ..< deq.count:
    yield deq.data[i]
    i = (i + 1) and deq.mask

iterator mitems*[T](deq: var Deque[T]): var T =
  ## Yield every element of `deq`.
  var i = deq.head
  for c in 0 ..< deq.count:
    yield deq.data[i]
    i = (i + 1) and deq.mask

iterator pairs*[T](deq: Deque[T]): tuple[key: int, val: T] =
  ## Yield every (position, value) of `deq`.
  var i = deq.head
  for c in 0 ..< deq.count:
    yield (c, deq.data[i])
    i = (i + 1) and deq.mask

proc contains*[T](deq: Deque[T], item: T): bool {.inline.} =
  ## Return true if `item` is in `deq` or false if not found. Usually used
  ## via the ``in`` operator. It is the equivalent of ``deq.find(item) >= 0``.
  ##
  ## .. code-block:: Nim
  ##   if x in q:
  ##     assert q.contains x
  for e in deq:
    if e == item: return true
  return false

proc expandIfNeeded[T](deq: var Deque[T]) =
  var cap = deq.mask + 1
  if unlikely(deq.count >= cap):
    var n = newSeq[T](cap * 2)
    for i, x in pairs(deq):  # don't use copyMem because the GC and because it's slower.
      shallowCopy(n[i], x)
    shallowCopy(deq.data, n)
    deq.mask = cap * 2 - 1
    deq.tail = deq.count
    deq.head = 0

proc addFirst*[T](deq: var Deque[T], item: T) =
  ## Add an `item` to the beginning of the `deq`.
  expandIfNeeded(deq)
  inc deq.count
  deq.head = (deq.head - 1) and deq.mask
  deq.data[deq.head] = item

proc addLast*[T](deq: var Deque[T], item: T) =
  ## Add an `item` to the end of the `deq`.
  expandIfNeeded(deq)
  inc deq.count
  deq.data[deq.tail] = item
  deq.tail = (deq.tail + 1) and deq.mask

proc peekFirst*[T](deq: Deque[T]): T {.inline.}=
  ## Returns the first element of `deq`, but does not remove it from the deque.
  emptyCheck(deq)
  result = deq.data[deq.head]

proc peekLast*[T](deq: Deque[T]): T {.inline.} =
  ## Returns the last element of `deq`, but does not remove it from the deque.
  emptyCheck(deq)
  result = deq.data[(deq.tail - 1) and deq.mask]

template destroy(x: untyped) =
  reset(x)

proc popFirst*[T](deq: var Deque[T]): T {.inline, discardable.} =
  ## Remove and returns the first element of the `deq`.
  emptyCheck(deq)
  dec deq.count
  result = deq.data[deq.head]
  destroy(deq.data[deq.head])
  deq.head = (deq.head + 1) and deq.mask

proc popLast*[T](deq: var Deque[T]): T {.inline, discardable.} =
  ## Remove and returns the last element of the `deq`.
  emptyCheck(deq)
  dec deq.count
  deq.tail = (deq.tail - 1) and deq.mask
  result = deq.data[deq.tail]
  destroy(deq.data[deq.tail])

proc clear*[T](deq: var Deque[T]) {.inline.} =
  ## Resets the deque so that it is empty.
  for el in mitems(deq): destroy(el)
  deq.count = 0
  deq.tail = deq.head

proc shrink*[T](deq: var Deque[T], fromFirst = 0, fromLast = 0) =
  ## Remove `fromFirst` elements from the front of the deque and
  ## `fromLast` elements from the back. If the supplied number of
  ## elements exceeds the total number of elements in the deque,
  ## the deque will remain empty.
  ##
  ## Any user defined destructors
  if fromFirst + fromLast > deq.count:
    clear(deq)
    return

  for i in 0 ..< fromFirst:
    destroy(deq.data[deq.head])
    deq.head = (deq.head + 1) and deq.mask

  for i in 0 ..< fromLast:
    destroy(deq.data[deq.tail])
    deq.tail = (deq.tail - 1) and deq.mask

  dec deq.count, fromFirst + fromLast

proc `$`*[T](deq: Deque[T]): string =
  ## Turn a deque into its string representation.
  result = "["
  for x in deq:
    if result.len > 1: result.add(", ")
    result.addQuoted(x)
  result.add("]")

# -------------------------------------------------- #
# HeapQueue : a container, in which you can push item, pop minimum item, peek minimum item efficiently.
# hq = newHeapQueue[int]() : init hq as an heapqueue.
# hq.push x : push item x in hq. O(log N)
# x = hq.pop : pop minimum element x in hq. O(log N)
# x = hq.peek : peek minimum element x in hq. O(1)
# tested in ABC128.E


type HeapQueue*[T] = distinct seq[T]

proc newHeapQueue*[T](): HeapQueue[T] {.inline.} = HeapQueue[T](newSeq[T]())
proc newHeapQueue*[T](h: var HeapQueue[T]) {.inline.} = h = HeapQueue[T](newSeq[T]())

proc len*[T](h: HeapQueue[T]): int {.inline.} = seq[T](h).len
proc `[]`*[T](h: HeapQueue[T], i: int): T {.inline.} = seq[T](h)[i]
proc `[]=`[T](h: var HeapQueue[T], i: int, v: T) {.inline.} = seq[T](h)[i] = v
proc add[T](h: var HeapQueue[T], v: T) {.inline.} = seq[T](h).add(v)

proc heapCmp[T](x, y: T): bool {.inline.} =
  return (x < y)

# 'heap' is a heap at all indices >= startpos, except possibly for pos.  pos
# is the index of a leaf with a possibly out-of-order value.  Restore the
# heap invariant.
proc siftdown[T](heap: var HeapQueue[T], startpos, p: int) =
  var pos = p
  var newitem = heap[pos]
  # Follow the path to the root, moving parents down until finding a place
  # newitem fits.
  while pos > startpos:
    let parentpos = (pos - 1) shr 1
    let parent = heap[parentpos]
    if heapCmp(newitem, parent):
      heap[pos] = parent
      pos = parentpos
    else:
      break
  heap[pos] = newitem

proc siftup[T](heap: var HeapQueue[T], p: int) =
  let endpos = len(heap)
  var pos = p
  let startpos = pos
  let newitem = heap[pos]
  # Bubble up the smaller child until hitting a leaf.
  var childpos = 2*pos + 1    # leftmost child position
  while childpos < endpos:
    # Set childpos to index of smaller child.
    let rightpos = childpos + 1
    if rightpos < endpos and not heapCmp(heap[childpos], heap[rightpos]):
      childpos = rightpos
    # Move the smaller child up.
    heap[pos] = heap[childpos]
    pos = childpos
    childpos = 2*pos + 1
  # The leaf at pos is empty now.  Put newitem there, and bubble it up
  # to its final resting place (by sifting its parents down).
  heap[pos] = newitem
  siftdown(heap, startpos, pos)

proc push*[T](heap: var HeapQueue[T], item: T) =
  ## Push item onto heap, maintaining the heap invariant.
  (seq[T](heap)).add(item)
  siftdown(heap, 0, len(heap)-1)

proc pop*[T](heap: var HeapQueue[T]): T =
  ## Pop the smallest item off the heap, maintaining the heap invariant.
  let lastelt = seq[T](heap).pop()
  if heap.len > 0:
    result = heap[0]
    heap[0] = lastelt
    siftup(heap, 0)
  else:
    result = lastelt

proc del*[T](heap: var HeapQueue[T], index: int) =
  ## Removes element at `index`, maintaining the heap invariant.
  swap(seq[T](heap)[^1], seq[T](heap)[index])
  let newLen = heap.len - 1
  seq[T](heap).setLen(newLen)
  if index < newLen:
    heap.siftup(index)

proc replace*[T](heap: var HeapQueue[T], item: T): T =
  ## Pop and return the current smallest value, and add the new item.
  ## This is more efficient than pop() followed by push(), and can be
  ## more appropriate when using a fixed-size heap.  Note that the value
  ## returned may be larger than item!  That constrains reasonable uses of
  ## this routine unless written as part of a conditional replacement:

  ##    if item > heap[0]:
  ##        item = replace(heap, item)
  result = heap[0]
  heap[0] = item
  siftup(heap, 0)

proc pushpop*[T](heap: var HeapQueue[T], item: T): T =
  ## Fast version of a push followed by a pop.
  if heap.len > 0 and heapCmp(heap[0], item):
    swap(item, heap[0])
    siftup(heap, 0)
  return item

proc peek*[T](heap: var HeapQueue[T]): T =
  result = heap[0]

proc peekOr*[T](heap: var HeapQueue[T], ifnil: T): T =
  if heap.len == 0:
    result = ifnil
  else:
    result = heap[0]
    
proc popOr*[T](heap: var HeapQueue[T], ifnil: T): T =
  if heap.len == 0:
    result = ifnil
  else:
    result = heap.pop()
    
# -------------------------------------------------- #

# Template for weighted directed graph problem
# tested in

# const
type Edge = tuple
  src: int
  dst: int
  cost: int

type PointAndDist = tuple
  point: int
  dist: int

proc `<`(x,y:Edge):bool = x.cost < y.cost
proc `>`(x,y:Edge):bool = x.cost > y.cost
proc `<`(x,y:PointAndDist):bool = x.dist < y.dist
proc `>`(x,y:PointAndDist):bool = x.dist > y.dist

const INF = 1000000000



# toutatsu kanou
proc get_isIkeru(N:int, edges_Src:seq[seq[Edge]]):seq[bool] =
  var isIkeru = newSeq[bool](N)
  for i in 0..<N:
    isIkeru[i] = false
  var que = newSeq[int]()

  isIkeru[0] = true
  que.add 0
  while que.len != 0:
    let src = que.pop()
    for e in edges_Src[src]:
      let dst = e.dst
      if not isIkeru[dst]:
        isIkeru[dst] = true
        que.add dst

  return isIkeru



## saitan keiro
# Dijkstra O((V+E)logV)
proc dijkstra(N:int, edges_Src:seq[seq[Edge]], siten:int=0):seq[int] =
  var distOf = newSeq[int](N)
  var predOf = newSeq[Edge](N)
  var que = newHeapQueue[PointAndDist]()
  var isDone = newSeq[bool](N)
  for i in 0..<N:
    if i==siten:
      distOf[i] = 0
    else:
      distOf[i] = INF
    predOf[i] = (-1,-1,INF)
    que.push( (i,distOf[i]) )
    isDone[i] = false

  while que.len != 0:
    let src = que.pop().point
    if isDone[src]: continue
    isDone[src] = true
    for e in edges_Src[src]:
      let dst = e.dst
      let alt = distOf[src] + e.cost
      if distOf[dst] > alt:
        distOf[dst] = alt
        predOf[dst] = e
        que.push( (dst,distOf[dst]) )

  return distOf



# Bellman–Ford O(VE) (negative cost ok)
proc bellman(N:int, edges:seq[Edge], siten:int=0): seq[int] =
  var distOf = newSeq[int](N)
  var predOf = newSeq[Edge](N)
  for i in 0..<N:
    distOf[i] = INF
    predOf[i] = (-1,-1,INF)
  distOf[siten] = 0

  for i in 1..N-1:
    for e in edges:
      if distOf[e.dst] > distOf[e.src] + e.cost:
        distOf[e.dst] = distOf[e.src] + e.cost
        predOf[e.dst] = e

  for e in edges:
    if distOf[e.dst] > distOf[e.src] + e.cost: # if negative cycle exists
      echo -1
      quit()

  return distOf



# Warshall-Floyd O(V^3) (Every point to point)
proc warshall(N:int, edges:seq[Edge]): seq[seq[int]] =
  var distFromTo = newSeq2[int](N,N)
  for i in 0..<N:
    for j in 0..<N:
      distFromTo[i][j] = INF
  for e in edges:
    distFromTo[e.src][e.dst] = e.cost

  for k in 0..<N:
    for i in 0..<N:
      for j in 0..<N:
        distFromTo[i][j] :<= distFromTo[i][k] + distFromTo[k][j]

  return distFromTo




# -------------------------------------------------- #


let (N,M) = input(int,2)

var edges_Src = newSeq2[Edge](N,0)

for _ in M:
  var (l,r,c) = input(int,3)
  l-=1
  r-=1
  edges_Src[l].add( (l,r,c) )

for i in 1..<N:
  edges_Src[i].add( (i,i-1,0) )

let result = dijkstra(N,edges_Src,0)[N-1]

if result==INF:
  echo -1
else:
  echo result
