This documentation is automatically generated by online-judge-tools/verification-helper

:heavy_check_mark: test/datastructure/persistent_union_find_test.cr

Depends on

Code

# verification-helper: PROBLEM https://judge.yosupo.jp/problem/persistent_unionfind
require "../../src/datastructure/persistent_union_find"
n, q = read_line.split.map(&.to_i)
uf = {-1 => PersistentUnionFind.new(n)}
q.times do |i|
  t, k, u, v = read_line.split.map(&.to_i)
  case t
  when 0
    uf[i] = uf[k].unite(u, v)[1]
  when 1
    puts uf[k].same?(u, v) ? 1 : 0
  end
end
# verification-helper: PROBLEM https://judge.yosupo.jp/problem/persistent_unionfind
# require "../../src/datastructure/persistent_union_find"
# require "./persistent_array"
class PersistentArray(T)
  CHILD_SIZE = 32

  private struct Node(T)
    property value : T
    property child : Node(T)*[CHILD_SIZE]

    def initialize
      @value = T.zero
      @child = StaticArray(Node(T)*, CHILD_SIZE).new(Pointer(Node(T)).null)
    end
  end

  protected def self.set(i : Int, value : T, ptr : Node(T)*) : Node(T)*
    result = Pointer(Node(T)).malloc
    result.copy_from(ptr, 1) if ptr
    if i == 0
      result.value.value = value
    else
      index = i % CHILD_SIZE
      result.value.child[index] = set(i // CHILD_SIZE, value, result.value.child[index])
    end
    result
  end

  @root : Node(T)*

  protected def initialize(@root)
  end

  def initialize
    @root = Pointer(Node(T)).null
  end

  def initialize(array : Array(T))
    @root = Pointer(Node(T)).null
    array.each_with_index do |x, i|
      destractive_set(i, x)
    end
  end

  def [](i : Int) : T
    get(i)
  end

  def get(i : Int) : T
    ptr = @root
    loop do
      if ptr.null?
        return T.zero
      elsif i == 0
        return ptr.value.value
      else
        ptr = ptr.value.child[i % CHILD_SIZE]
        i //= CHILD_SIZE
      end
    end
  end

  def set(i : Int, val : T) : self
    PersistentArray(T).new self.class.set(i, val, @root)
  end

  def destractive_set(i : Int, val : T) : T
    ptr = pointerof(@root)
    loop do
      if ptr.value.null?
        ptr.value = Pointer(Node(T)).malloc
      end
      if i == 0
        ptr.value.value.value = val
        break
      else
        ptr = ptr.value.value.child.to_unsafe + (i % CHILD_SIZE)
        i //= CHILD_SIZE
      end
    end
    val
  end

  def to_a(size : Int) : Array(T)
    (0...size).map { |i| get(i) }
  end
end

class PersistentUnionFind
  protected def initialize(@data : PersistentArray(Int32))
  end

  def initialize(size : Int)
    @data = PersistentArray(Int32).new Array.new(size, -1)
  end

  def root(x : Int)
    p = @data[x]
    p >= 0 ? root(p) : x
  end

  def same?(x : Int, y : Int)
    root(x) == root(y)
  end

  def size(x : Int)
    -@data[root(x)]
  end

  def unite(x : Int, y : Int) : {Bool, PersistentUnionFind}
    x, y = root(x), root(y)
    return {false, self} if x == y
    dx, dy = @data[x], @data[y]
    if dx > dy
      x, y = y, x
      dx, dy = dy, dx
    end
    {true, PersistentUnionFind.new(@data.set(x, dx + dy).set(y, x))}
  end
end

n, q = read_line.split.map(&.to_i)
uf = {-1 => PersistentUnionFind.new(n)}
q.times do |i|
  t, k, u, v = read_line.split.map(&.to_i)
  case t
  when 0
    uf[i] = uf[k].unite(u, v)[1]
  when 1
    puts uf[k].same?(u, v) ? 1 : 0
  end
end
Back to top page