Problem:
F - Acceleration of Network

インターネットと言う広大な海は少しずつ黒く塗りつぶされていった。

ボットの反乱、DDOS攻撃の嵐、ウィルスの蔓延、

何度も何度も繰り返されたクラッカーとの戦争で、人もインターネットもボロボロになった。

人の手では、インターネットはどうにもならない。

だから人は、とんでもない時間をかけて

インターネットを復旧できる「少女」を造った。

少女は、インターネットの手当をはじめた。

果てしなく広いインターネットの世界をどうにかしようと頑張った。

まだ少女ひとりでは撚り対線を織る事くらいしかできないけど、

長い長い時がすぎてインターネットが少し復旧すれば、

みんなと一緒に頑張れるだろうという期待をこめて。

問題文

少女はかつてインターネットに存在した N 個のサービスを復旧するために日々頑張っている．
現在を 0 日目とする．
インターネットがどの程度復旧しているかを復旧度という指標で表し，現在の復旧度は 0 であるとする．
少女は毎日作業をし，復旧度を 1 日につき 1 ずつ上げていく．
任意のまだ復旧していないサービス i は，復旧度が wi 以上になると自動的に復旧する．
サービス i が復旧すると，みんなが手伝ってくれることにより，復旧した次の日から xi 日間だけ作業がはかどり，復旧度の増加が加速する．
サービスには 3 つの種類があり，種類によって復旧度がどの程度増加するのかが異なる．
サービスの種類を 0, 1, 2 の番号で表すとする．
サービス i の種類を ti (∈ {0, 1, 2}) とすると，
サービス i が復旧してから d-1 日目から d 日目にかけて (1 ≤ d ≤ xi)，
ti=0 の場合は 1，
ti=1 の場合は d，
そして ti=2 の場合は d2 だけ，少女の作業とは別に復旧度が増加する．
また，同時に複数のサービスが復旧している場合，それぞれのサービスは独立に並行して復旧度を増加させる．

少女はサービスが復旧するまでにとんでもない時間がかかると思ったので，現在から何日目にサービスが復旧するか調べることにした．
またある日にち yj に復旧度がいくらになっているかも気になったので，それも Q 日分だけ調べることにした．

入力形式

入力は以下の形式で与えられる．

N Q
w1 t1 x1
...
wN tN xN
y1
...
yQ

出力形式

最初に N 行出力し，i 行目にはサービス i の復旧する日にちを出力せよ．次に Q 行出力し，j 行目には yj 日目に復旧度がいくらになっているかを出力せよ．
サービスが復旧する日にちが 3,652,425 を超える場合はMany years laterと出力せよ．

制約

0 ≤ N ≤ 105

1 ≤ Q ≤ 105

0 ≤ wi < 260

wi ≤ wi+1 (1 ≤ i < N)

ti ∈ {0, 1, 2}

1 ≤ xi ≤ 104

0 ≤ yj ≤ 3,652,425

yj < yj+1 (1 ≤ j < Q)

入力値はすべて整数である．

この問題の判定には，15 点分のテストケースのグループが設定されている．このグループに含まれるテストケースは上記の制約に加えて下記の制約も満たす．

N,Q,wi,yj ≤ 1,000

注意

0 日目の復旧度は 0 である．

wi=0 の時，サービス i は 0 日目に復旧する．

入出力例

入力例1

3 11
1 0 2
4 1 3
7 2 4
0
1
2
3
4
5
6
7
8
9
10

出力例1

1
3
4
0
1
3
5
7
11
19
29
46
47
48

入力例2

5 5
10000 0 20
10000 1 30
10000 0 40
10000 2 70
30000 2 10000
5000
10000
15000
20000
25000

出力例2

10000
10000
10000
10000
10039
5000
10000
40711690801
329498273301
333383477320

入力例3

2 2
3652425 0 1
3652426 2 10000
3652424
3652425

出力例3

3652425
Many years later
3652424
3652425

2つ目のサービスは復旧する日にちが 3,652,425 日を超えているのでMany years laterと出力している．

Writer : 森槙悟
Tester : 田村和範

Solution in Scala (judge verdict: Accepted)

import scala.collection.mutable

object Main extends App {
  import scala.io.StdIn._

  class State {
    var lastServiceChanged = ActualTime(0)
    var earnedBonusUntilLastServiceChanged = Progression(0)
    val additionalBonus = Bonus()
    def progressionAt(day: ActualTime): Progression = earnedBonusUntilLastServiceChanged + additionalBonus.bonusBetween(lastServiceChanged, day + 1) + day.toDayProgression
    def progressionAfter(day: ActualTime): Progression = progressionAt(lastServiceChanged + day.day)
    def addServiceBonus(serviceBonus: ServiceBonus): Unit = {
      val add = additionalBonus.bonusBetween(lastServiceChanged, serviceBonus.startTime)
      earnedBonusUntilLastServiceChanged += add
      lastServiceChanged = serviceBonus.startTime
      additionalBonus.add(serviceBonus)
    }
    def removeServiceBonus(serviceBonus: ServiceBonus): Unit = {
      val add = additionalBonus.bonusBetween(lastServiceChanged, serviceBonus.endTime)
      assert(add.progress >= 0)
      earnedBonusUntilLastServiceChanged += add
      lastServiceChanged = serviceBonus.endTime
      additionalBonus.remove(serviceBonus)
    }
  }
  val state = new State()
  val timeLimit = 3652426
  val Array(n, q) = readLine.trim.split(' ').map(_.toInt)
  val services: Array[Service] = Array.tabulate(n){i ⇒
    val Array(w, t, x) = readLine.trim.split(' ').map(_.toLong)
    new Service(i, w, t, x)
  }
  val actualTimeAtRecovery = Array.tabulate(services.length){ _ ⇒ ActualTime(0)}
  val queries = Array.tabulate(q){i ⇒
    Query(ActualTime(readLong), i)
  }
  val progressionAtQuery: Array[Progression] = Array.tabulate(queries.length){_ ⇒ Progression(0)}
  val eventsWithProgression = mutable.PriorityQueue()(Ordering.by[Service, BigInt](_.recoveryProgression.progress).reverse).also(_.enqueue(services:_*))
  val eventsWithActualTime = mutable.PriorityQueue()(Ordering.by[Event, BigInt](_.time.day).reverse).also(_.enqueue(queries:_*))
  while(eventsWithActualTime.nonEmpty || eventsWithProgression.nonEmpty){
    if (eventsWithActualTime.nonEmpty && (eventsWithProgression.isEmpty || eventsWithProgression.head.recoveryProgression.progress > state.progressionAt(eventsWithActualTime.head.time).progress)) {//イベントを進める
      eventsWithActualTime.dequeue() match {
        case Query(time, id) ⇒
          progressionAtQuery(id) = state.progressionAt(time)
        case BonusEnd(t, service) ⇒
          state.removeServiceBonus(service)
      }
    }else {//サービスを復旧
      val service = eventsWithProgression.dequeue()
      val recoveryTime = ActualTime(lowerBound(state.lastServiceChanged.day, timeLimit, service.recoveryProgression.progress))
      actualTimeAtRecovery(service.id) = recoveryTime
      val bonus = service.recoveryAt(recoveryTime)
      state.addServiceBonus(bonus)
      eventsWithActualTime.enqueue(BonusEnd(bonus.endTime, bonus))
    }

  }
  def lowerBound(from: BigInt, to: BigInt, target: BigInt): BigInt = {
    var left = from
    var right = to
    while(left < right){
      val mid = (left + right) / 2
      if (state.progressionAt(ActualTime(mid)).progress < target){
        left = mid + 1
      }else {
        right = mid
      }
    }
    right
  }
  if (actualTimeAtRecovery.nonEmpty) println(actualTimeAtRecovery.map(a ⇒ if (a.day >= timeLimit) "Many years later" else a.day.toString).mkString("\n"))
  println(progressionAtQuery.map(i ⇒ i.progress).mkString("\n"))
  case class ActualTime(day: BigInt) extends AnyVal {
    def +(that: BigInt): ActualTime = ActualTime(day + that)
    def -(that: ActualTime): ActualTime = ActualTime(day - that.day)
    def toDayProgression: Progression = Progression(day)
  }
  case class Progression(progress: BigInt) extends AnyVal {
    def +(that: Progression): Progression = Progression(progress + that.progress)
    def -(that: Progression): Progression = Progression(progress - that.progress)
  }
  sealed trait Event {
    def time: ActualTime
  }
  case class BonusEnd(time: ActualTime, service: ServiceBonus) extends Event
  case class Query(time: ActualTime, id: Int) extends Event
  implicit class Scope[T](val value: T) extends AnyVal {
    @inline def also(@inline func: T ⇒ Unit): T = {
      func(value)
      value
    }
    @inline def let[A](@inline func: T ⇒ A): A = func(value)
  }
  case class Bonus(var type0: Type0AdditionalBonus = Type0AdditionalBonus(), var type1: Type1AdditionalBonus = Type1AdditionalBonus(), var type2: Type2AdditionalBonus = Type2AdditionalBonus()) {
    def addBonus(type0Bonus: Type0Bonus): Unit = type0 = type0.addService(type0Bonus)
    def addBonus(type1Bonus: Type1Bonus): Unit = type1 = type1.addService(type1Bonus)
    def addBonus(type2Bonus: Type2Bonus): Unit = type2 = type2.addService(type2Bonus)
    def add(bonus: ServiceBonus): Unit = bonus match {
      case b: Type0Bonus ⇒ addBonus(b)
      case b: Type1Bonus ⇒ addBonus(b)
      case b: Type2Bonus ⇒ addBonus(b)
    }
    def removeBonus(type0Bonus: Type0Bonus): Unit = type0 = type0.removeService(type0Bonus)
    def removeBonus(type1Bonus: Type1Bonus): Unit = type1 = type1.removeService(type1Bonus)
    def removeBonus(type2Bonus: Type2Bonus): Unit = type2 = type2.removeService(type2Bonus)
    def remove(bonus: ServiceBonus): Unit = bonus match {
      case b: Type0Bonus ⇒ removeBonus(b)
      case b: Type1Bonus ⇒ removeBonus(b)
      case b: Type2Bonus ⇒ removeBonus(b)
    }
    def bonusBetween(from: ActualTime, until: ActualTime): Progression = {//from until until のイベントが処理済み
      type0.bonusBetween(from, until) + type1.bonusBetween(from, until) + type2.bonusBetween(from, until)
    }
  }
  class Service(val id: Int, w: Long, t: Long, x: Long) {
    def recoveryProgression: Progression = Progression(w)
    def recoveryAt(time: ActualTime): ServiceBonus = t match {
      case 0 ⇒ Type0Bonus(time, x.toInt)
      case 1 ⇒ Type1Bonus(time, x.toInt)
      case 2 ⇒ Type2Bonus(time, x.toInt)
      case _ ⇒ ???
    }
  }
  sealed trait ServiceBonus {
    def x: Int
    def startTime: ActualTime
    def endTime: ActualTime = ActualTime(startTime.day + x)
  }
  case class Type0Bonus(startTime: ActualTime, x: Int) extends ServiceBonus
  case class Type1Bonus(startTime: ActualTime, x: Int) extends ServiceBonus
  case class Type2Bonus(startTime: ActualTime, x: Int) extends ServiceBonus
  trait AdditionalBonus {//epochDay => epochBonus それ以外の日は計算で求める
    protected def bonusAt(day: ActualTime): Progression = bonusBetween(day, day + 1)
    protected def baseBonusAt(day: ActualTime): Progression = baseBonusFromEpoch(day + 1) - baseBonusFromEpoch(day)
    protected def baseBonusFromEpoch(until: ActualTime): Progression
    protected def serviceCount: Int
    protected def epochBonus: Progression
    protected def epochDay: ActualTime
    def bonusBetween(from: ActualTime, until: ActualTime): Progression = if (from == until) Progression(0) else if (from == epochDay) epochBonus + baseBonusFromEpoch(until) - baseBonusFromEpoch(from + 1) else baseBonusFromEpoch(until) - baseBonusFromEpoch(from)
  }
  case class Type0AdditionalBonus(override val serviceCount: Int = 0, override val epochDay: ActualTime = ActualTime(0), override val epochBonus: Progression = Progression(0)) extends AdditionalBonus {
    override protected def baseBonusFromEpoch(until: ActualTime): Progression = Progression(serviceCount * (until - epochDay).day)
    def addService(serviceBonus: Type0Bonus): Type0AdditionalBonus = Type0AdditionalBonus(serviceCount + 1, serviceBonus.startTime, bonusAt(serviceBonus.startTime))
    def removeService(serviceBonus: Type0Bonus): Type0AdditionalBonus = Type0AdditionalBonus(serviceCount - 1, serviceBonus.endTime, bonusAt(serviceBonus.endTime))
  }
  case class Type1AdditionalBonus(override val serviceCount: Int = 0, override val epochDay: ActualTime = ActualTime(0), override val epochBonus: Progression = Progression(0), baseBonus: Progression = Progression(0)) extends AdditionalBonus {
    override protected def baseBonusFromEpoch(until: ActualTime): Progression = (until - epochDay).day.let(t ⇒ Progression(baseBonus.progress * t + t * (t - 1) / 2 * serviceCount))
    def addService(serviceBonus: Type1Bonus): Type1AdditionalBonus = Type1AdditionalBonus(serviceCount + 1, serviceBonus.startTime, bonusAt(serviceBonus.startTime), baseBonusAt(serviceBonus.startTime))
    def removeService(serviceBonus: Type1Bonus): Type1AdditionalBonus = Type1AdditionalBonus(serviceCount - 1, serviceBonus.endTime, bonusAt(serviceBonus.endTime), baseBonusAt(serviceBonus.endTime) - (serviceBonus.endTime - serviceBonus.startTime).toDayProgression)
  }
  case class Type2AdditionalBonus(override val serviceCount: Int = 0, override val epochDay: ActualTime = ActualTime(0), override val epochBonus: Progression = Progression(0), baseBonus: Progression = Progression(0), sumDays: BigInt = 0) extends AdditionalBonus {
    override protected def baseBonusFromEpoch(until: ActualTime): Progression = (until - epochDay).day.let(t ⇒ Progression(baseBonus.progress * t + t * (t - 1) / 2 * (2 * sumDays - serviceCount) + serviceCount * t * (t - 1) * (2 * t - 1) / 6 + serviceCount * t * (t - 1) / 2))
    def addService(serviceBonus: Type2Bonus): Type2AdditionalBonus = Type2AdditionalBonus(serviceCount + 1, serviceBonus.startTime, bonusAt(serviceBonus.startTime), baseBonusAt(serviceBonus.startTime), sumDays + serviceCount * (serviceBonus.startTime - epochDay).day)
    def removeService(serviceBonus: Type2Bonus): Type2AdditionalBonus = Type2AdditionalBonus(serviceCount - 1, serviceBonus.endTime, bonusAt(serviceBonus.endTime), baseBonusAt(serviceBonus.endTime) - Progression((serviceBonus.endTime - serviceBonus.startTime).day.let(it ⇒ it * it)), sumDays + serviceCount * (serviceBonus.endTime - epochDay).day - (serviceBonus.endTime - serviceBonus.startTime).day)
  }
}