AtCoder problem 037

C++ solution:

Crystal solution: # ac-library.cr by hakatashi https://github.com/google/ac-library.cr
#
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

module AtCoder
  # Implements [atcoder::segtree](https://atcoder.github.io/ac-library/master/document_en/segtree.html).
  #
  # The identity element will be implicitly defined as nil, so you don't
  # have to manually define it. In the other words, you cannot include
  # nil into an element of the monoid.
  #
  # ```
  # tree = AtCoder::SegTree.new((0...100).to_a) { |a, b| [a, b].min }
  # tree[10...50] # => 10
  # ```
  class SegTree(T)
    property values : Array(T)

    def initialize(values : Array(T))
      initialize(values) { |a, b| a > b ? a : b }
    end

    def initialize(values : Array(T), &@operator : T, T -> T)
      @values = values
      @segments = Array(T | Nil).new(2 ** ::Math.log2(values.size).ceil.to_i - 1, nil)

      # initialize segments
      (@segments.size - 1).downto(0) do |i|
        child1 = nil.as(T | Nil)
        child2 = nil.as(T | Nil)
        if i * 2 + 1 < @segments.size
          child1 = @segments[i * 2 + 1]
          child2 = @segments[i * 2 + 2]
        else
          if i * 2 + 1 - @segments.size < @values.size
            child1 = @values[i * 2 + 1 - @segments.size]
          end
          if i * 2 + 2 - @segments.size < @values.size
            child2 = @values[i * 2 + 2 - @segments.size]
          end
        end
        @segments[i] = operate(child1, child2)
      end
    end

    @[AlwaysInline]
    private def operate(a : T | Nil, b : T | Nil)
      if a.nil?
        b
      elsif b.nil?
        a
      else
        @operator.call(a, b)
      end
    end

    # Implements atcoder::segtree.set(index, value)
    def []=(index : Int, value : T)
      @values[index] = value

      parent_index = (index + @segments.size - 1) // 2
      while parent_index >= 0
        i = parent_index
        child1 = nil.as(T | Nil)
        child2 = nil.as(T | Nil)
        if i * 2 + 1 < @segments.size
          child1 = @segments[i * 2 + 1]
          child2 = @segments[i * 2 + 2]
        else
          if i * 2 + 1 - @segments.size < @values.size
            child1 = @values[i * 2 + 1 - @segments.size]
          end
          if i * 2 + 2 - @segments.size < @values.size
            child2 = @values[i * 2 + 2 - @segments.size]
          end
        end
        @segments[i] = operate(child1, child2)
        parent_index = (parent_index - 1) // 2
      end
    end

    # Implements atcoder::segtree.get(index)
    def [](index : Int)
      @values[index]
    end

    # Implements atcoder::segtree.prod(l, r)
    def [](range : Range(Int, Int))
      a = range.begin
      b = range.exclusive? ? range.end : range.end + 1
      get_value(a, b, 0, 0...(@segments.size + 1)).not_nil!
    end

    def get_value(a : Int, b : Int, segment_index : Int, range : Range(Int, Int))
      if range.end <= a || b <= range.begin
        return nil
      end

      if a <= range.begin && range.end <= b
        if segment_index < @segments.size
          return @segments[segment_index]
        else
          return @values[segment_index - @segments.size]
        end
      end

      range_median = (range.begin + range.end) // 2
      child1 = get_value(a, b, 2 * segment_index + 1, range.begin...range_median)
      child2 = get_value(a, b, 2 * segment_index + 2, range_median...range.end)

      operate(child1, child2)
    end

    # compatibility with ac-library

    # Implements atcoder::segtree.set(index, value)
    # alias of `.[]=`
    def set(index : Int, value : T)
      self.[]=(index, value)
    end

    # Implements atcoder::segtree.get(index)
    # alias of `.[]`
    def get(index : Int)
      self.[](index)
    end

    # Implements atcoder::segtree.prod(left, right)
    def prod(left : Int, right : Int)
      self.[](left...right)
    end

    # Implements atcoder::segtree.all_prod(l, r)
    def all_prod
      self.[](0...@values.size)
    end

    # FIXME: Unimplemented
    def max_right
      raise NotImplementedError.new
    end

    # FIXME: Unimplemented
    def max_left
      raise NotImplementedError.new
    end
  end
end

w, n = read_line.split.map(&.to_i)
seg = AtCoder::SegTree.new([0i64] + [-1i64] * w) { |a, b| {a, b}.max }
n.times do
  l, r, v = read_line.split.map(&.to_i)
  (0..w).reverse_each do |i|
    ll, rr = i - r, i - l
    if 0 <= rr
      val = seg[{0, ll}.max..rr]
      seg[i] = {seg[i], val + v}.max if val != -1
    end
  end
end
puts seg[w]





Kuin solution: func main()
	var w: int :: cui@inputInt()
	var n: int :: cui@inputInt()
	var l: []int :: #[n]int
	var r: []int :: #[n]int
	var v: []int :: #[n]int
	for i(0, n - 1)
		do l[i] :: cui@inputInt()
		do r[i] :: cui@inputInt()
		do v[i] :: cui@inputInt()
	end for
	
	var dp: [][]int :: #[n + 1, w + 1]int
	for j(0, w)
		do dp[0][j] :: lib@intMin
	end for
	do dp[0][0] :: 0
	for i(0, n - 1)
		var seg: @SegmentTree :: (#@SegmentTree).init(w + 1)
		for j(0, w)
			do seg.update(j, dp[i][j])
		end for
		for j(0, w)
			var val: int :: seg.query([j - r[i], 0].max(), j - l[i] + 1)
			do dp[i + 1][j] :: lib@max(dp[i][j], val + v[i])
		end for
	end for
	
	var ans: int :: [dp[n][w], -1].max()
	do cui@print("\{ans}\n")
end func

class SegmentTree()
	const invalid: int :: lib@intMin
	var size: int
	var node: []int
	+func init(n: int): SegmentTree
		do me.size :: 1
		while(me.size < n)
			do me.size :* 2
		end while
		do me.node :: #[2 * me.size]int
		for i(0, 2 * me.size - 1)
			do me.node[i] :: invalid
		end for
		ret me
	end func
	+func update(idx: int, val: int)
		do idx :+ me.size - 1
		do me.node[idx] :: val
		while(idx > 0)
			do idx :: (idx - 1) / 2
			do me.node[idx] :: lib@max(me.node[2 * idx + 1], me.node[2 * idx + 2])
		end while
	end func
	+func query(a: int, b: int): int
		ret me.querySub(a, b, 0, 0, me.size)
	end func
	func querySub(a: int, b: int, k: int, l: int, r: int): int
		if(b <= l | r <= a)
			ret invalid
		end if
		if(a <= l & r <= b)
			ret me.node[k]
		end if
		var vl: int :: me.querySub(a, b, 2 * k + 1, l, (l + r) / 2)
		var vr: int :: me.querySub(a, b, 2 * k + 2, (l + r) / 2, r)
		ret lib@max(vl, vr)
	end func
	+*func toStr(): []char
		var padding: int :: 1
		while(padding <= me.size)
			do padding :* 2
		end while
		do padding :- 1
		var res: []char :: ""
		var s: int :: 0
		var e: int :: 0
		var n: int :: 1
		const digit: int :: 6
		var fmt: []char :: " \{digit}d"
		var strInf: []char :: " ".repeat(digit - 3) ~ "inf"
		while(padding > 0)
			do padding :/ 2
			for i(s, e)
				do res :~ " ".repeat((digit + 1) * padding)
				do res :~ "\{me.node[i] = invalid ?(strInf, me.node[i].toStrFmt(fmt))}|"
			end for
			do res :~ "\n"
			do n :* 2
			do s :: e + 1
			do e :: s + n - 1
		end while
		ret res
	end func
end class