Решение
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.InputStreamReader
import java.io.OutputStreamWriter
// Класс дерева Фенвика для работы с Long-значениями.
class FenwickTree(val n: Int) {
private val tree = LongArray(n + 1) { 0L }
fun update(i: Int, delta: Long) {
var idx = i
while (idx <= n) {
tree[idx] += delta
idx += idx and -idx
}
}
fun query(i: Int): Long {
var sum = 0L
var idx = i
while (idx > 0) {
sum += tree[idx]
idx -= idx and -idx
}
return sum
}
// Находит минимальный индекс, такой что префиксная сумма >= target.
fun lowerBound(target: Long): Int {
var idx = 0
var bit = Integer.highestOneBit(n)
var curTarget = target
while (bit > 0) {
val next = idx + bit
if (next <= n && tree[next] < curTarget) {
curTarget -= tree[next]
idx = next
}
bit = bit shr 1
}
return idx + 1
}
}
fun main(args: Array<String>) {
val reader = BufferedReader(InputStreamReader(System.`in`))
val writer = BufferedWriter(OutputStreamWriter(System.out))
// Читаем количество участников (n – четное)
val n = reader.readLine().toInt()
val K = n / 2 // нам нужно выбрать n/2 участников с наибольшими delta, что эквивалентно сумме n/2 наименьших для вычитания.
// Читаем исходные значения навыков разработки и управления.
val aList = reader.readLine().split(" ").map { it.toLong() }
val bList = reader.readLine().split(" ").map { it.toLong() }
// Глобальная сумма a[i] для вычисления ответа: answer = S_a - (сумма n/2 наименьших delta)
var globalSumA = aList.sum()
// Вычисляем для каждого участника начальное delta = a[i] - b[i].
val diff = LongArray(n + 1)
for (i in 1..n)
diff[i] = aList[i - 1] - bList[i - 1]
// Читаем количество запросов.
val m = reader.readLine().toInt()
// Сохраним все запросы, чтобы можно было собрать множество возможных значений diff.
val queries = Array(m) {
val parts = reader.readLine().split(" ")
Triple(parts[0].toInt(), parts[1].toInt(), parts[2].toLong())
}
// Собираем множество candidate значений diff (начальные + все изменения).
val allDiffs = ArrayList<Long>()
for (i in 1..n)
allDiffs.add(diff[i])
val sim = diff.copyOf()
for (q in queries) {
val num = q.first
val type = q.second
val d = q.third
if (type == 1) {
sim[num] = sim[num] + d
} else {
sim[num] = sim[num] - d
}
allDiffs.add(sim[num])
}
// Координатное сжатие: получаем отсортированный список уникальных значений.
allDiffs.sort()
val compList = ArrayList<Long>()
compList.add(allDiffs[0])
for (i in 1 until allDiffs.size) {
if (allDiffs[i] != compList.last())
compList.add(allDiffs[i])
}
val compSize = compList.size
// Создаем маппинг: значение -> позиция (1-индексировано)
val compMap = HashMap<Long, Int>()
for (i in compList.indices) {
compMap[compList[i]] = i + 1
}
// Создаем два BIT-а: один для частот, другой для суммы.
val bitFreq = FenwickTree(compSize)
val bitSum = FenwickTree(compSize)
// Инициализируем BIT’ы начальными значениями diff.
for (i in 1..n) {
val pos = compMap[diff[i]]!!
bitFreq.update(pos, 1)
bitSum.update(pos, diff[i])
}
// Функция для получения суммы K наименьших элементов diff из BIT.
fun queryBottomK(k: Int): Long {
// Находим минимальный индекс, такой что суммарная частота >= k.
val idx = bitFreq.lowerBound(k.toLong())
val countBefore = bitFreq.query(idx - 1)
val sumBefore = bitSum.query(idx - 1)
val remainder = k - countBefore
val value = compList[idx - 1]
return sumBefore + remainder * value
}
// После каждого запроса ответ вычисляется как: answer = globalSumA - (сумма n/2 наименьших diff).
// (Заметим, что sum(a) - (сумма n/2 минимальных delta) равен суммарной пользе оптимального разделения.)
val output = StringBuilder()
for (q in queries) {
val num = q.first
val type = q.second
val d = q.third
// Удаляем старое значение diff[num] из BIT.
val oldVal = diff[num]
val oldPos = compMap[oldVal]!!
bitFreq.update(oldPos, -1)
bitSum.update(oldPos, -oldVal)
// Обновляем diff и, если нужно, глобальную сумму a.
if (type == 1) {
diff[num] += d
globalSumA += d
} else {
diff[num] -= d
}
val newVal = diff[num]
val newPos = compMap[newVal]!!
bitFreq.update(newPos, 1)
bitSum.update(newPos, newVal)
// Получаем сумму n/2 наименьших значений diff.
val bottomSum = queryBottomK(K)
val ans = globalSumA - bottomSum
output.append(ans).append("\\n")
}
writer.write(output.toString())
writer.flush()
reader.close()
writer.close()
}