AtCoder problem 029

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::lazy_segtree](https://atcoder.github.io/ac-library/master/document_en/lazysegtree.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.
  #
  # Similarly, the identity map of F 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 set F.
  #
  # ```
  # op = ->(a : Int32, b : Int32) { [a, b].min }
  # mapping = ->(f : Int32, x : Int32) { f }
  # composition = ->(a : Int32, b : Int32) { a }
  # tree = AtCoder::LazySegTree(Int32, Int32).new((0...100).to_a, op, mapping, composition)
  # tree[10...50] # => 10
  # tree[20...60] = 0
  # tree[50...80] # => 0
  # ```
  class LazySegTree(S, F)
    getter values : Array(S | Nil)

    def initialize(values : Array(S), @operator : S, S -> S, @application : F, S -> S, @composition : F, F -> F)
      @values = values.map { |v| v.as(S | Nil) }
      segment_size = 2 ** ::Math.log2(@values.size).ceil.to_i - 1
      @segments = Array(S | Nil).new(segment_size, nil)
      @applicators = Array(F | Nil).new(segment_size, nil)

      # initialize segments
      (@segments.size - 1).downto(0) do |i|
        child1 = nil.as(S | Nil)
        child2 = nil.as(S | 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

    # FIXME: Unimplemented
    def set
      raise NotImplementedError.new
    end

    # Implements atcoder::lazy_segtree.apply(index, applicator).
    def []=(index : Int, applicator : F)
      apply_range(index, index + 1, applicator, 0, 0...(@segments.size + 1))
    end

    # Implements atcoder::lazy_segtree.apply(left, right, applicator).
    def []=(range : Range(Int, Int), applicator : F)
      l = range.begin
      r = range.exclusive? ? range.end : range.end + 1
      apply_range(l, r, applicator, 0, 0...(@segments.size + 1))
    end

    # Implements atcoder::lazy_segtree.get(index).
    def [](index : Int)
      get_range(index, index + 1, 0, 0...(@segments.size + 1)).not_nil!
    end

    # Implements atcoder::lazy_segtree.prod(left, right).
    def [](range : Range(Int, Int))
      l = range.begin
      r = range.exclusive? ? range.end : range.end + 1
      get_range(l, r, 0, 0...(@segments.size + 1)).not_nil!
    end

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

    @[AlwaysInline]
    private def apply(f : F | Nil, x : S | Nil)
      if f.nil?
        x
      elsif x.nil?
        nil
      else
        @application.call(f, x)
      end
    end

    @[AlwaysInline]
    private def compose(a : F | Nil, b : F | Nil)
      if a.nil?
        b
      elsif b.nil?
        a
      else
        @composition.call(a, b)
      end
    end

    # Evaluates segment, whose range is `range`. `range` is exclusive here.
    #
    # Preconditions:
    # * segment_index < @segments.size
    # * range.end - range.begin > 1
    def eval_segment(segment_index : Int, range : Range(Int, Int))
      applicator = @applicators[segment_index]
      return if applicator.nil?

      @segments[segment_index] = apply(applicator, @segments[segment_index])

      if range.end - range.begin > 2
        @applicators[segment_index * 2 + 1] = compose(applicator, @applicators[segment_index * 2 + 1])
        @applicators[segment_index * 2 + 2] = compose(applicator, @applicators[segment_index * 2 + 2])
      else
        @values[segment_index * 2 + 1 - @segments.size] = apply(applicator, @values[segment_index * 2 + 1 - @segments.size])
        @values[segment_index * 2 + 2 - @segments.size] = apply(applicator, @values[segment_index * 2 + 2 - @segments.size])
      end

      @applicators[segment_index] = nil
    end

    # Applies applicator `f` onto segment, whose range is `range`. `range` is exclusive here.
    def apply_range(a : Int, b : Int, f : F, segment_index : Int, range : Range(Int, Int))
      if segment_index >= @segments.size + @values.size
        return nil
      end

      if segment_index < @segments.size
        eval_segment(segment_index, range)
      end

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

      if a <= range.begin && range.end <= b
        if segment_index < @segments.size
          @applicators[segment_index] = compose(@applicators[segment_index], f)
          eval_segment(segment_index, range)
          return @segments[segment_index]
        else
          @values[segment_index - @segments.size] = apply(f, @values[segment_index - @segments.size])
          return @values[segment_index - @segments.size]
        end
      end

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

      @segments[segment_index] = operate(child1, child2)
      @segments[segment_index]
    end

    # Gets evaluated value of a segment, whose range is `range`. `range` is exclusive here.
    def get_range(a : Int, b : Int, segment_index : Int, range : Range(Int, Int))
      if range.end <= a || b <= range.begin
        return nil
      end

      if segment_index < @segments.size
        eval_segment(segment_index, range)
      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_range(a, b, segment_index * 2 + 1, range.begin...range_median)
      child2 = get_range(a, b, segment_index * 2 + 2, range_median...range.end)

      operate(child1, child2)
    end

    # Implements atcoder::lazy_segtree.all_prod().
    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

op = ->(x : Int32, y : Int32) { {x, y}.max }
mapping = ->(f : Int32, _s : Int32) { f }
composition = ->(f : Int32, _g : Int32) { f }

w, n = read_line.split.map(&.to_i)
seg = AtCoder::LazySegTree(Int32, Int32).new([0] * w, op, mapping, composition)
n.times do
  l, r = read_line.split.map(&.to_i.pred)
  height = seg[l..r] + 1
  puts height
  seg[l..r] = height
end





Kuin solution: func main()
	var w: int :: cui@inputInt()
	var n: int :: cui@inputInt()
	var segmentTree: @SegmentTree :: (#@SegmentTree).init(w)
	do segmentTree.updateRange(0, w, 0)
	for(1, n)
		var l: int :: cui@inputInt() - 1
		var r: int :: cui@inputInt()
		var ans: int :: -segmentTree.query(l, r) + 1
		do cui@print("\{ans}\n")
		do segmentTree.updateRange(l, r, -ans)
	end for
end func

class SegmentTree()
	const inf_: int :: lib@intMax
	var size: int
	var node: []int
	var lasy: []int
	+func init(n: int): SegmentTree
		do me.size :: 1
		while(me.size < n)
			do me.size :* 2
		end while
		do me.node :: [inf_].repeat(2 * me.size)
		do me.lasy :: ##me.node
		ret me
	end func
	func eval(k: int)
		if(me.lasy[k] = inf_)
			ret
		end if
		if(k < me.size - 1)
			do me.lasy[k * 2 + 1] :: me.lasy[k]
			do me.lasy[k * 2 + 2] :: me.lasy[k]
		end if
		do me.node[k] :: me.lasy[k]
		do me.lasy[k] :: inf_
	end func
	+func update(idx: int, val: int)
		do me.updateRange(idx, idx + 1, val)
	end func
	+func updateRange(a: int, b: int, val: int)
		do me.updateRangeSub(a, b, val, 0, 0, me.size)
	end func
	+func updateRangeSub(a: int, b: int, val: int, k: int, l: int, r: int)
		do me.eval(k)
		if(a <= l & r <= b)
			do me.lasy[k] :: val
			do me.eval(k)
		elif(a < r & l < b)
			do me.updateRangeSub(a, b, val, k * 2 + 1, l, (l + r) / 2)
			do me.updateRangeSub(a, b, val, k * 2 + 2, (l + r) / 2, r)
			do me.node[k] :: lib@min(me.node[k * 2 + 1], me.node[k * 2 + 2])
		end if
	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
		do me.eval(k)
		if(b <= l | r <= a)
			ret inf_
		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@min(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] = inf_ ?(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