https://coderun.yandex.ru/problem/kolya-and-data-centers Средняя

Решение

import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.InputStreamReader
import java.io.OutputStreamWriter
import kotlin.math.min
import kotlin.math.max

// Узел сегментного дерева: хранит значение (prod) и индекс (для разрешения равенств – выбираем меньший индекс)
data class Node(val prod: Long, val idx: Int)

fun main(args: Array<String>) {
    val reader = BufferedReader(InputStreamReader(System.`in`))
    val writer = BufferedWriter(OutputStreamWriter(System.out))
    
    // Считываем n, m, q
    val firstLine = reader.readLine().split(" ")
    val n = firstLine[0].toInt()
    val m = firstLine[1].toInt()
    val q = firstLine[2].toInt()
    
    // Для каждого датацентра (индексы 0..n-1)
    // R – число перезапусков (начальное 0)
    // A – число рабочих серверов (начальное m)
    val R = IntArray(n) { 0 }
    val A = IntArray(n) { m }
    // prod[i] = R[i]*A[i], изначально 0
    val prod = LongArray(n) { 0L }
    // version[i]: начнем с 1; при RESET будем увеличивать
    val version = IntArray(n) { 1 }
    // Для каждого датацентра создадим массив для серверов (размер m)
    // Каждый элемент – int, обозначающий версию, в которой сервер был отключён; изначально 0 (не соответствует текущей version)
    val disabled = Array(n) { IntArray(m) { 0 } }
    
    // Теперь реализуем итератив сегментное дерево для точечных обновлений.
    // Найдем минимальную степень двойки >= n.
    var size = 1
    while (size < n) size *= 2
    // Для max-дерева: identity – Node(-1, n) (поскольку все prod>=0)
    val INF = 1_000_000_000_000_000_000L // большого значения не понадобится; для min используем, например, 1e15+1
    // Для min-дерева: identity – Node(1e15, n) (продукты не превысят примерно 1e11)
    val identityMax = Node(-1L, n)
    val identityMin = Node(1_000_000_000_000_000L, n)
    
    val segMax = Array(2 * size) { identityMax }
    val segMin = Array(2 * size) { identityMin }
    
    // Инициализируем листья по данным prod; изначально все 0
    for (i in 0 until n) {
        segMax[size + i] = Node(prod[i], i)
        segMin[size + i] = Node(prod[i], i)
    }
    for (i in n until size) {
        segMax[size + i] = identityMax
        segMin[size + i] = identityMin
    }
    // Функции слияния для max и min:
    fun mergeMax(a: Node, b: Node): Node {
        return when {
            a.prod > b.prod -> a
            a.prod < b.prod -> b
            else -> if (a.idx < b.idx) a else b
        }
    }
    fun mergeMin(a: Node, b: Node): Node {
        return when {
            a.prod < b.prod -> a
            a.prod > b.prod -> b
            else -> if (a.idx < b.idx) a else b
        }
    }
    // Построим дерево.
    for (i in size - 1 downTo 1) {
        segMax[i] = mergeMax(segMax[2 * i], segMax[2 * i + 1])
        segMin[i] = mergeMin(segMin[2 * i], segMin[2 * i + 1])
    }
    
    // Функция обновления для датацентра index (0-indexed) с новым значением prod.
    fun update(index: Int, value: Long) {
        var pos = index + size
        segMax[pos] = Node(value, index)
        segMin[pos] = Node(value, index)
        pos /= 2
        while (pos >= 1) {
            segMax[pos] = mergeMax(segMax[2 * pos], segMax[2 * pos + 1])
            segMin[pos] = mergeMin(segMin[2 * pos], segMin[2 * pos + 1])
            pos /= 2
        }
    }
    
    // Процесс обработки q событий
    for (qq in 0 until q) {
        val parts = reader.readLine().split(" ")
        when (parts[0]) {
            "RESET" -> {
                // RESET i
                val iDC = parts[1].toInt() - 1
                R[iDC]++              // увеличиваем число перезапусков
                version[iDC]++        // увеличиваем версию
                A[iDC] = m            // восстанавливаем число рабочих серверов
                prod[iDC] = R[iDC].toLong() * A[iDC].toLong()
                update(iDC, prod[iDC])
            }
            "DISABLE" -> {
                // DISABLE i j
                val iDC = parts[1].toInt() - 1
                val jServer = parts[2].toInt() - 1
                // Если сервер уже отключён (в текущей версии) – ничего не делаем.
                if (disabled[iDC][jServer] != version[iDC]) {
                    disabled[iDC][jServer] = version[iDC]  // помечаем его как отключённый в текущей версии
                    if (A[iDC] > 0) {
                        A[iDC]--
                        prod[iDC] = R[iDC].toLong() * A[iDC].toLong()
                        update(iDC, prod[iDC])
                    }
                }
            }
            "GETMAX" -> {
                // Выводим (1-indexированный) номер датацентра с наибольшим prod
                writer.write("${segMax[1].idx + 1}")
                writer.newLine()
            }
            "GETMIN" -> {
                // Выводим (1-indexированный) номер датацентра с наименьшим prod
                writer.write("${segMin[1].idx + 1}")
                writer.newLine()
            }
        }
    }
    
    writer.flush()
    writer.close()
    reader.close()
}