結果

問題 No.1778 括弧列クエリ / Bracketed Sequence Query
ユーザー yudedakoyudedako
提出日時 2022-01-28 22:42:58
言語 Scala(Beta)
(3.4.0)
結果
TLE  
実行時間 -
コード長 6,045 bytes
コンパイル時間 14,424 ms
コンパイル使用メモリ 265,856 KB
実行使用メモリ 157,768 KB
最終ジャッジ日時 2023-08-28 21:13:07
合計ジャッジ時間 38,902 ms
ジャッジサーバーID
(参考情報)
judge13 / judge11
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 TLE -
testcase_01 TLE -
testcase_02 TLE -
testcase_03 TLE -
testcase_04 TLE -
testcase_05 TLE -
testcase_06 TLE -
testcase_07 AC 1,223 ms
68,372 KB
testcase_08 TLE -
testcase_09 -- -
testcase_10 -- -
testcase_11 -- -
testcase_12 -- -
testcase_13 -- -
testcase_14 -- -
testcase_15 -- -
testcase_16 -- -
testcase_17 -- -
testcase_18 -- -
testcase_19 -- -
testcase_20 -- -
testcase_21 -- -
testcase_22 -- -
testcase_23 -- -
testcase_24 -- -
testcase_25 -- -
testcase_26 -- -
testcase_27 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

import scala.annotation.tailrec
import scala.collection.immutable
import scala.collection.immutable.TreeSet
import scala.io.StdIn.readLine
import scala.math.*

import scala.annotation.tailrec

object Patricia:
  private sealed trait Node:
    val prefix: Int
  private object Node:
    private def leftMostOne(value: Int): Int =
      var result = 0
      for i <- Array(4, 3, 2, 1, 0) do
        if value >>> (result + (1 << i)) > 0 then
          result += 1 << i
      1 << result
    private def apply(left: Node, right: Node): Node =
      val mask = -leftMostOne(left.prefix ^ right.prefix)
      val prefix = (left.prefix | right.prefix) & mask
      Branch(prefix, left, right)
    def insert(node: Node, newValue: Int): Node =
      node match
        case Branch(prefix, left, right) =>
          val mask = -(prefix & -prefix) << 1
          if (prefix & mask) != (newValue & mask) then
            if prefix < newValue then Node(node, Leaf(newValue))
            else Node(Leaf(newValue), node)
          else
            if newValue < (prefix & right.prefix) then
              val newLeft = insert(left, newValue)
              if newLeft eq left then node
              else Branch(prefix, newLeft, right)
            else
              val newRight = insert(right, newValue)
              if newRight eq right then node
              else Branch(prefix, left, newRight)
        case Leaf(prefix) =>
          if prefix == newValue then node
          else if prefix < newValue then Node(node, Leaf(newValue))
          else Node(Leaf(newValue), node)
    def erase(node: Node, value: Int): Option[Node] =
      node match
        case Branch(prefix, left, right) =>
          val mask = -(prefix & -prefix) << 1
          if (prefix & mask) != (value & mask) then Some(node)
          else
            if value < (right.prefix & prefix) then
              erase(left, value) match
                case Some(newLeft) =>
                  if newLeft eq left then Some(node)
                  else Some(Node(newLeft, right))
                case None  => Some(right)
            else
              erase(right, value) match
                case Some(newRight) =>
                  if newRight eq right then Some(node)
                  else Some(Node(left, newRight))
                case None => Some(left)
        case Leaf(oldValue) =>
          if oldValue == value then None
          else Some(node)
    @tailrec def minValue(node: Node): Int =
      node match
        case Branch(_, left, _) => minValue(left)
        case Leaf(prefix) => prefix
    def lowerBound(node: Node, value: Int): Option[Int] =
      node match
        case Branch(prefix, left , right) =>
          val mask = -(prefix & -prefix) << 1
          if (prefix & mask) < (value & mask) then None
          if (value & mask) < (prefix & mask) then Some(minValue(left))
          else if value < (right.prefix & prefix) then Some(lowerBound(left, value).getOrElse(minValue(right)))
          else lowerBound(right, value)
        case Leaf(prefix) =>
          if prefix < value then None
          else Some(prefix)
    def upperBound(node: Node, value: Int): Option[Int] =
      node match
        case Branch(prefix, left , right) =>
          val mask = -(prefix & -prefix) << 1
          if (prefix & mask) < (value & mask) then None
          else if (value & mask) < (prefix & mask) then Some(minValue(left))
          else if value < (right.prefix & prefix) then Some(upperBound(left, value).getOrElse(minValue(right)))
          else upperBound(right, value)
        case Leaf(prefix) =>
          if prefix <= value then None
          else Some(prefix)
    def copyToArray(node: Node, dest: Array[Int], position: Int): Int =
      node match
        case Branch(prefix, left, right) =>
          copyToArray(right, dest, copyToArray(left, dest, position))
        case Leaf(prefix) =>
          dest(position) = prefix
          position + 1


  private case class Branch(override val prefix: Int, val left: Node, val right: Node) extends Node
  private case class Leaf(override val prefix: Int) extends Node

class Patricia private(private val root: Option[Patricia.Node], val size: Int):
  import Patricia.Node.*
  import Patricia.*
  def this() =
    this(None, 0)
  def inserted(value: Int): Patricia =
    root match
      case Some(r) =>
        val newRoot = insert(r, value)
        if newRoot eq r then this
        else Patricia(Some(newRoot), size + 1)
      case None => Patricia(Some(Patricia.Leaf(value)), 1)
  def erased(value: Int): Patricia =
    root match
      case Some(r) =>
        erase(r, value) match
          case Some(newRoot) =>
            if newRoot eq r then this
            else Patricia(Some(newRoot), size - 1)
          case None => Patricia(None, 0)
      case None => this
  def lowerBound(value: Int): Option[Int] =
    root.flatMap(Node.lowerBound(_, value))
  def upperBound(value: Int): Option[Int] =
    root.flatMap(Node.upperBound(_, value))
  def toArray: Array[Int] =
    root match
      case Some(r) =>
        val result = Array.fill(size){0}
        copyToArray(r, result, 0)
        result
      case None => Array()
  def +(value: Int): Patricia = inserted(value)
  def minAfter(value: Int): Option[Int] = lowerBound(value)
@main def main =
  val Array(n, q) = readLine().split(' ').map(_.toInt)
  val s = readLine()
  val queries = Array.fill(q){
    val Array(x, y) = readLine().split(' ').map(_.toInt - 1)
    min(x, y) -> max(x, y)
  }
  var stack = Nil: List[Int]
  val pair = Array.fill(n){-1}
  for (c, i) <- s.zipWithIndex do
    c match
      case '(' => stack ::= i
      case ')' =>
        val h::t = stack
        pair(i) = h
        pair(h) = i
        stack = t
  val set = Array.fill(n){Patricia()}
  for i <- 0 until n do
    if i > 0 then
      set(i) = set(i - 1)
    if s(i) == '(' then
      set(i) = set(i) + pair(i)
  for (x, y) <- queries do
    val result = set(x).minAfter(y).map(right => s"${pair(right) + 1} ${right + 1}").getOrElse("-1")
    println(result)

0