Haskell Number Of Disc Intersections
import Data.Array (Array, accumArray, listArray, (!))
numberOfDiscIntersections :: [Int] -> Int
numberOfDiscIntersections a = go 0 0 [0 .. c - 1]
where
c = length a
arr = listArray (0, c - 1) a :: Array Int Int
startCounts = accumArray (+) 0 (0, c - 1) [(max 0 (i - arr ! i), 1) | i <- [0 .. c - 1]] :: Array Int Int
endCounts = accumArray (+) 0 (0, c - 1) [(min (c - 1) (i + arr ! i), 1) | i <- [0 .. c - 1]] :: Array Int Int
go _ total [] = total
go active total (k : ks)
| total' > 10000000 = -1
| otherwise = go active' total' ks
where
s = startCounts ! k
e = endCounts ! k
total' = total + active * s + (s * (s - 1)) `div` 2
active' = active + s - e
This sorts disc start and end points and counts active overlaps without comparing every pair directly.