Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

Problem H: Sequence

Problem

項数$L$の等差数列が$N$個ある。$i$番目の等差数列の初項は$a_i$で公差は$d_i$である。1番目の数列から順番に1番目の数列, 2番目の数列, ..., $N$番目の数列と並べ、そうしてできた数列を$A$とする。その後、$A$から長さ$K$の任意の区間を選んで、新たに数列$B$を作るとき、数列$B$の和を最大化せよ。

Input

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

$N$ $L$ $K$

$a_1$ $d_1$

$a_2$ $d_2$

...

$a_N$ $d_N$

1行目に3つの整数$N$, $L$, $K$が空白区切りで与えられる。

続く$N$行に、$i$個目の等差数列の情報$a_i$, $d_i$が空白区切りで与えられる。

Constraints

入力は以下の条件を満たす。

$1 \leq N \leq 10^5$

$1 \leq L \leq 10^5$

$1 \leq K \leq N\times L$

$0 \leq a_i \leq 10^5$

$1 \leq d_i \leq 10^3$

入力はすべて整数

Output

数列$B$の和の最大値を1行に出力する。

Sample Input 1

3 3 5
0 3
2 2
4 1

Sample Output 1

25

数列$A$は$0,3,6,2,4,6,4,5,6$となる。この数列の第5項から第9項までを数列$B$とすれば、数列$B$の和は25となり、これが最大である。

Sample Input 2

3 3 5
0 10
8 1
11 1

Sample Output 2

58

Solution in Scala (judge verdict: Accepted)

import scala.io.StdIn._
object Main extends App {
  val Array(n, l, k) = readLine.trim.split(' ').map(_.toLong)
  val sequence = Array.tabulate(n.toInt){_ ⇒
    val Array(a, d) = readLine.trim.split(' ').map(_.toLong)
    (a, d)
  }
  val sums = sequence.map{seq ⇒ all(seq)}
  var max = 0L
  for (i ← 1 until n.toInt) sums(i) += sums(i - 1)
  for (left ← 0 until n.toInt) {
    if (k / l >= 1 && (0L until n).contains(left + k / l)) {
      val temp = sums((left + k / l).toInt - 1) - sums(left) + calMaxSum(sequence(left), sequence((left + k / l).toInt), k - l * (k / l - 1))
      if (temp > max) max = temp
    }
    if ((0L until n).contains(left + k / l + 1)) {
      val temp = sums((left + k / l).toInt) - sums(left) + calMaxSum(sequence(left), sequence((left + k / l).toInt + 1), k - l * (k / l))
      if (temp > max) max = temp
    }
  }
  if (k == l * n) max = sums.last
  println(max)
  def calMaxSum(left: (Long, Long), right: (Long, Long), length: Long): Long = {
    if (length >= l) {
      val initialDiff = right._1 + right._2 * (length % l) - left._1
      val diffDiff = right._2 - left._2
      if (initialDiff >= 0 && diffDiff < 0) {
          val shift = (initialDiff - diffDiff - 1) / -diffDiff
          if (length % l + shift >= l) sum_seq(left, length % l, right, l)
          else sum_seq(left, l - shift, right, length % l + shift)
      }else {
        math.max(sum_seq(left, l, right, length % l), sum_seq(left, length % l, right, l))
      }
    }else {
      val initialDiff = right._1 - left._1 - left._2 * (l - length)
      val diffDiff = right._2 - left._2
      if (initialDiff >= 0 && diffDiff < 0) {
        val shift = (initialDiff - diffDiff - 1) / -diffDiff
        if (length < shift) sum_seq(right, length)
        else sum_seq(left, length - shift, right, shift)
      }else {
        math.max(sum_seq(left, length, right, 0), sum_seq(left, 0, right, length))
      }
    }
  }
  def all(sequence: (Long, Long)): Long = {
    sequence._1 * l + l * (l - 1) / 2 * sequence._2
  }
  def sum_seq(left: (Long, Long), leftCount: Long, right: (Long, Long), rightCount: Long): Long = {
    sum_seq(left, l - leftCount, l) + sum_seq(right, rightCount)
  }
  def sum_seq(sequence: (Long, Long), from: Long, until: Long): Long = {
    sum_seq(sequence, until) - sum_seq(sequence, from)
  }
  def sum_seq(sequence: (Long, Long), until: Long): Long = {
    sequence._1 * until + until * (until - 1) / 2 * sequence._2
  }
}