https://coderun.yandex.ru/problem/party-pizza Сложная

Решение

import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.InputStreamReader
import java.io.OutputStreamWriter
import java.util.StringTokenizer

fun main() {
    val reader = BufferedReader(InputStreamReader(System.`in`), 1 shl 20)
    val writer = BufferedWriter(OutputStreamWriter(System.out), 1 shl 20)

    val stNM = StringTokenizer(reader.readLine())
    val n = stNM.nextToken().toInt()
    val m = stNM.nextToken().toInt()

    val a = IntArray(n + 1)
    val stA = StringTokenizer(reader.readLine())
    for (i in 1..n) {
        a[i] = stA.nextToken().toInt()
    }

    val pos = Array(n + 1) { mutableListOf<Int>() }
    for (i in 1..n) {
        pos[a[i]].add(i)
    }

    val size = 1 shl (32 - Integer.numberOfLeadingZeros(n - 1))
    val treeSize = size shl 1
    val cand = IntArray(treeSize)
    val cnt = IntArray(treeSize)

    for (i in 0 until n) {
        cand[size + i] = a[i + 1]
        cnt[size + i] = 1
    }
    for (i in size - 1 downTo 1) {
        val lc = i shl 1
        val rc = lc or 1
        val c1 = cand[lc]; val c2 = cand[rc]
        val k1 = cnt[lc]; val k2 = cnt[rc]
        if (c1 == c2) {
            cand[i] = c1
            cnt[i] = k1 + k2
        } else if (k1 > k2) {
            cand[i] = c1
            cnt[i] = k1 - k2
        } else {
            cand[i] = c2
            cnt[i] = k2 - k1
        }
    }

    fun query(l0: Int, r0: Int): Int {
        var l = l0 + size - 1
        var r = r0 + size - 1
        var lcand = 0; var lcount = 0
        var rcand = 0; var rcount = 0

        while (l <= r) {
            if ((l and 1) == 1) {
                val vc = cand[l]; val vk = cnt[l]
                if (lcand == vc) {
                    lcount += vk
                } else if (lcount > vk) {
                    lcount -= vk
                } else {
                    lcand = vc
                    lcount = vk - lcount
                }
                l++
            }
            if ((r and 1) == 0) {
                val vc = cand[r]; val vk = cnt[r]
                if (rcand == vc) {
                    rcount += vk
                } else if (vk > rcount) {
                    rcand = vc
                    rcount = vk - rcount
                } else {
                    rcount -= vk
                }
                r--
            }
            l = l shr 1
            r = r shr 1
        }
        return if (lcand == rcand) {
            lcand
        } else if (lcount > rcount) {
            lcand
        } else {
            rcand
        }
    }

    fun lowerBound(list: List<Int>, key: Int): Int {
        var lo = 0
        var hi = list.size
        while (lo < hi) {
            val mid = (lo + hi) ushr 1
            if (list[mid] < key) lo = mid + 1 else hi = mid
        }
        return lo
    }
    fun upperBound(list: List<Int>, key: Int): Int {
        var lo = 0
        var hi = list.size
        while (lo < hi) {
            val mid = (lo + hi) ushr 1
            if (list[mid] <= key) lo = mid + 1 else hi = mid
        }
        return lo
    }

    repeat(m) {
        val st = StringTokenizer(reader.readLine())
        val l = st.nextToken().toInt()
        val r = st.nextToken().toInt()
        val c = query(l, r)
        if (c == 0) {
            writer.write("0\\n")
        } else {
            val occ = upperBound(pos[c], r) - lowerBound(pos[c], l)
            writer.write(if (occ * 2 > r - l + 1) "$c\\n" else "0\\n")
        }
    }

    writer.flush()
}