Решение
import java.io.BufferedReader
import java.io.BufferedWriter
import java.io.InputStreamReader
import java.io.OutputStreamWriter
import kotlin.math.sqrt
import kotlin.math.abs
import kotlin.math.min
fun main(args: Array<String>) {
val reader = BufferedReader(InputStreamReader(System.`in`))
val writer = BufferedWriter(OutputStreamWriter(System.out))
// Считываем количество частей для f и g.
val line = reader.readLine().split(" ")
val n = line[0].toInt() // число участков для f
val m = line[1].toInt() // число участков для g
// Считываем границы для функции f (n+1 чисел)
val fBoundaries = reader.readLine().split(" ").map { it.toDouble() }.toDoubleArray()
// Считываем n строк с коэффициентами полинома для f: a, b, c (f(x)=a*x^2+b*x+c)
val fA = DoubleArray(n)
val fB = DoubleArray(n)
val fC = DoubleArray(n)
for (i in 0 until n) {
val parts = reader.readLine().split(" ")
fA[i] = parts[0].toDouble()
fB[i] = parts[1].toDouble()
fC[i] = parts[2].toDouble()
}
// Считываем границы для функции g (m+1 чисел)
val gBoundaries = reader.readLine().split(" ").map { it.toDouble() }.toDoubleArray()
// Считываем m строк с коэффициентами полинома для g.
val gA = DoubleArray(m)
val gB = DoubleArray(m)
val gC = DoubleArray(m)
for (i in 0 until m) {
val parts = reader.readLine().split(" ")
gA[i] = parts[0].toDouble()
gB[i] = parts[1].toDouble()
gC[i] = parts[2].toDouble()
}
// Общая область интегрирования [L0, L_end] – гарантировано, что fBoundaries[0]=gBoundaries[0] и fBoundaries[n]=gBoundaries[m].
val L0 = fBoundaries[0]
val Lend = fBoundaries[n]
var totalArea = 0.0
var i = 0 // индекс для f
var j = 0 // индекс для g
var currentX = L0
val eps = 1e-12
// Выполняем двухуказательный проход по промежуткам
while (currentX < Lend - eps && i < n && j < m) {
// Следующая граница – минимум следующей границы у f и у g.
val nextX = min(fBoundaries[i+1], gBoundaries[j+1])
// На данном интервале:
// f(x)= fA[i]*x^2 + fB[i]*x + fC[i],
// g(x)= gA[j]*x^2 + gB[j]*x + gC[j].
// Пусть p(x)= f(x)-g(x)= A*x^2 + B*x + C.
val A = fA[i] - gA[j]
val B = fB[i] - gB[j]
val C = fC[i] - gC[j]
totalArea += integrateAbsQuadratic(A, B, C, currentX, nextX)
// Сдвигаем указатели, если достигли границы соответствующего кусочка.
if (abs(fBoundaries[i+1] - nextX) < eps) i++
if (abs(gBoundaries[j+1] - nextX) < eps) j++
currentX = nextX
}
writer.write(String.format("%.10f", totalArea))
writer.newLine()
writer.flush()
reader.close()
writer.close()
}
// Функция вычисления интеграла от |A*x^2+B*x+C| на промежутке [L, R]
fun integrateAbsQuadratic(A: Double, B: Double, C: Double, L: Double, R: Double): Double {
val eps = 1e-12
if (R - L < eps) return 0.0
// Если полином практически постоянен: A и B малы.
if (abs(A) < eps && abs(B) < eps) {
return abs(C) * (R - L)
}
// Определим антидериватив F(x) = A/3*x^3 + B/2*x^2 + C*x.
fun F(x: Double): Double = A * x * x * x / 3.0 + B * x * x / 2.0 + C * x
// p(x) = A*x^2+B*x+C.
fun p(x: Double): Double = A * x * x + B * x + C
// Массив для точек разбиения. В худшем случае добавятся две корневые точки плюс L и R.
val pts = DoubleArray(4)
var cnt = 0
pts[cnt++] = L
if (abs(A) < eps) {
// Линейный случай: p(x) = B*x+C, при B != 0 (иначе обработан выше)
if (abs(B) >= eps) {
val root = -C / B
if (root > L + eps && root < R - eps) {
pts[cnt++] = root
}
}
} else {
// Квадратичный случай
val D = B * B - 4.0 * A * C
if (D >= 0.0) {
val sqrtD = sqrt(D)
val r1 = (-B - sqrtD) / (2.0 * A)
val r2 = (-B + sqrtD) / (2.0 * A)
if (r1 > L + eps && r1 < R - eps) pts[cnt++] = r1
if (r2 > L + eps && r2 < R - eps) pts[cnt++] = r2
}
}
pts[cnt++] = R
// Сортировка (количество точек не более 4)
for (i in 0 until cnt) {
for (j in i + 1 until cnt) {
if (pts[i] > pts[j]) {
val tmp = pts[i]
pts[i] = pts[j]
pts[j] = tmp
}
}
}
var area = 0.0
// Интегрируем по каждому отрезку, где знак p(x) постоянен.
for (i in 0 until cnt - 1) {
val aInt = pts[i]
val bInt = pts[i+1]
if (bInt - aInt < eps) continue
val mid = (aInt + bInt) / 2.0
val sign = if (p(mid) >= 0) 1.0 else -1.0
area += sign * (F(bInt) - F(aInt))
}
return abs(area)
}