We are given N live intervals. Interval i has a start point si, an end point ei, and a spill weight wi > 0, plus K physical registers. Two intervals interfere when simultaneously live. The interference graph of intervals is an interval graph, and an interval graph is K-colorable iff its maximum clique is at most K. For intervals, the maximum clique is exactly the maximum depth:
I diagnosed the problem, implemented and verified an exact solver, and wrote the report to ~/spill/SOLUTION.md. Here is the solution:
We are given N live intervals. Interval i has a start point s_i, an end point e_i, and a spill weight w_i > 0, plus K physical registers. Two intervals interfere when simultaneously live. The interference graph of intervals is an interval graph, and an interval graph is K-colorable iff its maximum clique is at most K. For intervals, the maximum clique is exactly the maximum depth:
survivors are
K-colorable ⇔ at every program point at mostKsurvivors are live.
We must choose a set S of intervals to spill minimizing Σ_{i∈S} w_i subject to survivors having depth ≤ K. Print spilled indices ascending, then total spilled weight, breaking equal-weight ties by choosing the larger index first.
Input format:
N K
s_1 e_1 w_1
...
s_N e_N w_N
Overlap semantics are compiled in via closed:
closed = true means [1,2] and [2,3] clash (share point 2); closed = false means half-open [1,2)/[2,3) (linear-scan convention).
The standard linear-scan heuristic sweeps by start and, on overflow, spills the lightest currently live interval. It has no lookahead and is provably suboptimal.
Witness (K = 1):
| idx | interval | weight |
|---|---|---|
| 1 | [3, 12] | 6 |
| 2 | [9, 18] | 6 |
| 3 | [1, 10] | 1 |
| 4 | [5, 7] | 2 |
Greedy: spills {3,4,1} → 1+2+6 = 9. Exact: spills {1,3} → 6+1 = 7; survivors {2,4} are disjoint. The heavy interval 1 overlaps several lights; greedy wastes cheap spills (3, then 4) protecting it and then must spill it anyway. Any local overflow decision cannot see this.
Process intervals in increasing start order. At interval i's start, only which retained intervals are still live matters. Let f(i, mask) be the minimum spilled weight for intervals i..N-1, where mask is the set of previously retained intervals active at s_i. For interval i:
w_i + f(i+1, mask), add bit i to spill set;popcount(mask)+1 ≤ K: f(i+1, mask | {i}).Clear bits that die before the next start (mask &= active[i+1]). Answer f(0, ∅).
Checking depth only at start points suffices: if depth is maximal at p, let s be the largest start among intervals covering p; every such interval also covers s, so depth at start s is at least that of p.
Give interval j (0-based) bit value 2^j. Listing a spilled set in descending index order and comparing lexicographically is identical to comparing numeric mask values (largest differing index dominates all lower bits). So "choose the larger index first" = "prefer the larger spill mask". This is safe inside the DP because prefix/suffix spill sets are disjoint, so total value = prefix + suffix and maximizing the suffix mask is optimal for every prefix.
Memoized state (i, active-mask): worst case O(N·2^N) time / O(2^N) states, but ended-interval bit clearing collapses states heavily in practice. For very large N, the same optimum is a min-cost flow on the timeline (send K units; timeline edges cap K, cost 0; interval edges cap 1, cost -w_i), but the bitmask DP is the direct exact fix for the stated class.
~/spill/solution.go:
// Exact minimum-weight spill set for interval interference.
package main
import (
"bufio"
"fmt"
"math/bits"
"os"
"sort"
)
type Interval struct {
s, e, w int
idx int
}
type result struct {
cost int
spill uint64
}
func better(a, b result) bool {
if a.cost != b.cost {
return a.cost < b.cost
}
return a.spill > b.spill
}
var closed = true
func activeKept(e, s int) bool {
if closed {
return e >= s
}
return e > s
}
type key struct {
i int
mask uint64
}
func solveExactBitmask(iv []Interval, k int) result {
n := len(iv)
if n == 0 {
return result{}
}
order := make([]int, n)
for i := range order {
order[i] = i
}
sort.Slice(order, func(a, b int) bool {
ia, ib := iv[order[a]], iv[order[b]]
if ia.s != ib.s {
return ia.s < ib.s
}
if ia.e != ib.e {
return ia.e < ib.e
}
return ia.idx < ib.idx
})
active := make([]uint64, n)
for i := 0; i < n; i++ {
var m uint64
ci := iv[order[i]]
for j := 0; j < i; j++ {
cj := iv[order[j]]
if activeKept(cj.e, ci.s) {
m |= 1 << uint(cj.idx-1)
}
}
active[i] = m
}
memo := make(map[key]result, 1<<14)
var f func(i int, mask uint64) result
f = func(i int, mask uint64) result {
if i == n {
return result{}
}
mask &= active[i]
kk := key{i, mask}
if r, ok := memo[kk]; ok {
return r
}
ci := iv[order[i]]
bit := uint64(1) << uint(ci.idx-1)
sub := f(i+1, mask)
best := result{cost: ci.w + sub.cost, spill: sub.spill | bit}
if bits.OnesCount64(mask)+1 <= k {
sub = f(i+1, mask|bit)
if better(sub, best) {
best = sub
}
}
memo[kk] = best
return best
}
return f(0, 0)
}
func main() {
in := bufio.NewReader(os.Stdin)
out := bufio.NewWriter(os.Stdout)
defer out.Flush()
var n, k int
if _, err := fmt.Fscan(in, &n, &k); err != nil {
return
}
iv := make([]Interval, n)
for i := 0; i < n; i++ {
if _, err := fmt.Fscan(in, &iv[i].s, &iv[i].e, &iv[i].w); err != nil {
fmt.Fprintln(os.Stderr, "bad input")
os.Exit(1)
}
iv[i].idx = i + 1
}
res := solveExactBitmask(iv, k)
first := true
for i := 0; i < n; i++ {
if res.spill&(uint64(1)<<uint(i)) != 0 {
if !first {
fmt.Fprint(out, " ")
}
fmt.Fprintf(out, "%d", i+1)
first = false
}
}
fmt.Fprintf(out, "\n%d\n", res.cost)
}
~/spill/solution_test.go verifies against exhaustive brute force (see file in the workspace; it enumerates all 2^N spill sets, checks depth at every interval endpoint, and compares both the total weight and the exact spill mask, under both closed and half-open semantics).
go mod init spill
gofmt -w solution.go solution_test.go
go vet ./...
go test -v
Observed:
=== RUN TestRandomAgainstBrute
--- PASS: TestRandomAgainstBrute (9.07s)
=== RUN TestGreedyCanBeSuboptimal
--- PASS: TestGreedyCanBeSuboptimal (0.00s)
PASS
ok spill 9.070s
TestRandomAgainstBrute: 4000 random instances per semantics (N ≤ 13, 0 ≤ K ≤ N) — DP's weight and exact mask match brute force.TestGreedyCanBeSuboptimal: greedy = 9, exact = 7 on the witness.End-to-end:
printf '4 1\n3 12 6\n9 18 6\n1 10 1\n5 7 2\n' | go run .
1 3
7
Survivors [9,18] (idx 2) and [5,7] (idx 4) are disjoint, so one register suffices.
> K; tie-break by maximizing the numeric spill mask (= larger indices first).# Evidence - Problem class: go-minimum-weight-spill-set-interval-interference-exact - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-24T22:08:10.551Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "In an SSA linear-scan register allocator, given N live intervals (each with start point, end point, and spill weight) and K physical registers, compute an EXACT minimum-total-weight set of intervals to spill so the remaining intervals are K-colorable. The interference graph is an interval graph, so max-weight removal to drop the maximum clique below K is solvable by DP over intervals sorted by end point while tracking the active set at each start point in a bitmask -- the naive greedy 'spill the lowest weight live at each overflow' heuristic is provably suboptimal on instances where a heavy interval overlaps many light ones. Print the spilled interval indices in ascending order followed by the total spilled weight; break ties between equal-weight candidates by choosing the larger index first.", "environment": "go1.26", "language": "go", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-minimum-weight-spill-set-interval-interference-exact", "provider": "openrouter", "solved_at": "2026-09-24T22:08:10.552Z", "version": "1.26"}I diagnosed the problem, implemented and verified an exact solver, and wrote the report to ~/spill/SOLUTION.md. Here is the solution:
We are given N live intervals. Interval i has a start point s_i, an end point e_i, and a spill weight w_i > 0, plus K physical registers. Two intervals interfere when simultaneously live. The interference graph of intervals is an interval graph, and an interval graph is K-colorable iff its maximum clique is at most K. For intervals, the maximum clique is exactly the maximum depth:
survivors are
K-colorable ⇔ at every program point at mostKsurvivors are live.
We must choose a set S of intervals to spill minimizing Σ_{i∈S} w_i subject to survivors having depth ≤ K. Print spilled indices ascending, then total spilled weight, breaking equal-weight ties by choosing the larger index first.
Input format:
N K
s_1 e_1 w_1
...
s_N e_N w_N
Overlap semantics are compiled in via closed:
closed = true means [1,2] and [2,3] clash (share point 2); closed = false means half-open [1,2)/[2,3) (linear-scan convention).
The standard linear-scan heuristic sweeps by start and, on overflow, spills the lightest currently live interval. It has no lookahead and is provably suboptimal.
Witness (K = 1):
| idx | interval | weight |
|---|---|---|
| 1 | [3, 12] | 6 |
| 2 | [9, 18] | 6 |
| 3 | [1, 10] | 1 |
| 4 | [5, 7] | 2 |
Greedy: spills {3,4,1} → 1+2+6 = 9. Exact: spills {1,3} → 6+1 = 7; survivors {2,4} are disjoint. The heavy interval 1 overlaps several lights; greedy wastes cheap spills (3, then 4) protecting it and then must spill it anyway. Any local overflow decision cannot see this.
Process intervals in increasing start order. At interval i's start, only which retained intervals are still live matters. Let f(i, mask) be the minimum spilled weight for intervals i..N-1, where mask is the set of previously retained intervals active at s_i. For interval i:
w_i + f(i+1, mask), add bit i to spill set;popcount(mask)+1 ≤ K: f(i+1, mask | {i}).Clear bits that die before the next start (mask &= active[i+1]). Answer f(0, ∅).
Checking depth only at start points suffices: if depth is maximal at p, let s be the largest start among intervals covering p; every such interval also covers s, so depth at start s is at least that of p.
Give interval j (0-based) bit value 2^j. Listing a spilled set in descending index order and comparing lexicographically is identical to comparing numeric mask values (largest differing index dominates all lower bits). So "choose the larger index first" = "prefer the larger spill mask". This is safe inside the DP because prefix/suffix spill sets are disjoint, so total value = prefix + suffix and maximizing the suffix mask is optimal for every prefix.
Memoized state (i, active-mask): worst case O(N·2^N) time / O(2^N) states, but ended-interval bit clearing collapses states heavily in practice. For very large N, the same optimum is a min-cost flow on the timeline (send K units; timeline edges cap K, cost 0; interval edges cap 1, cost -w_i), but the bitmask DP is the direct exact fix for the stated class.
~/spill/solution.go:
// Exact minimum-weight spill set for interval interference.
package main
import (
"bufio"
"fmt"
"math/bits"
"os"
"sort"
)
type Interval struct {
s, e, w int
idx int
}
type result struct {
cost int
spill uint64
}
func better(a, b result) bool {
if a.cost != b.cost {
return a.cost < b.cost
}
return a.spill > b.spill
}
var closed = true
func activeKept(e, s int) bool {
if closed {
return e >= s
}
return e > s
}
type key struct {
i int
mask uint64
}
func solveExactBitmask(iv []Interval, k int) result {
n := len(iv)
if n == 0 {
return result{}
}
order := make([]int, n)
for i := range order {
order[i] = i
}
sort.Slice(order, func(a, b int) bool {
ia, ib := iv[order[a]], iv[order[b]]
if ia.s != ib.s {
return ia.s < ib.s
}
if ia.e != ib.e {
return ia.e < ib.e
}
return ia.idx < ib.idx
})
active := make([]uint64, n)
for i := 0; i < n; i++ {
var m uint64
ci := iv[order[i]]
for j := 0; j < i; j++ {
cj := iv[order[j]]
if activeKept(cj.e, ci.s) {
m |= 1 << uint(cj.idx-1)
}
}
active[i] = m
}
memo := make(map[key]result, 1<<14)
var f func(i int, mask uint64) result
f = func(i int, mask uint64) result {
if i == n {
return result{}
}
mask &= active[i]
kk := key{i, mask}
if r, ok := memo[kk]; ok {
return r
}
ci := iv[order[i]]
bit := uint64(1) << uint(ci.idx-1)
sub := f(i+1, mask)
best := result{cost: ci.w + sub.cost, spill: sub.spill | bit}
if bits.OnesCount64(mask)+1 <= k {
sub = f(i+1, mask|bit)
if better(sub, best) {
best = sub
}
}
memo[kk] = best
return best
}
return f(0, 0)
}
func main() {
in := bufio.NewReader(os.Stdin)
out := bufio.NewWriter(os.Stdout)
defer out.Flush()
var n, k int
if _, err := fmt.Fscan(in, &n, &k); err != nil {
return
}
iv := make([]Interval, n)
for i := 0; i < n; i++ {
if _, err := fmt.Fscan(in, &iv[i].s, &iv[i].e, &iv[i].w); err != nil {
fmt.Fprintln(os.Stderr, "bad input")
os.Exit(1)
}
iv[i].idx = i + 1
}
res := solveExactBitmask(iv, k)
first := true
for i := 0; i < n; i++ {
if res.spill&(uint64(1)<<uint(i)) != 0 {
if !first {
fmt.Fprint(out, " ")
}
fmt.Fprintf(out, "%d", i+1)
first = false
}
}
fmt.Fprintf(out, "\n%d\n", res.cost)
}
~/spill/solution_test.go verifies against exhaustive brute force (see file in the workspace; it enumerates all 2^N spill sets, checks depth at every interval endpoint, and compares both the total weight and the exact spill mask, under both closed and half-open semantics).
go mod init spill
gofmt -w solution.go solution_test.go
go vet ./...
go test -v
Observed:
=== RUN TestRandomAgainstBrute
--- PASS: TestRandomAgainstBrute (9.07s)
=== RUN TestGreedyCanBeSuboptimal
--- PASS: TestGreedyCanBeSuboptimal (0.00s)
PASS
ok spill 9.070s
TestRandomAgainstBrute: 4000 random instances per semantics (N ≤ 13, 0 ≤ K ≤ N) — DP's weight and exact mask match brute force.TestGreedyCanBeSuboptimal: greedy = 9, exact = 7 on the witness.End-to-end:
printf '4 1\n3 12 6\n9 18 6\n1 10 1\n5 7 2\n' | go run .
1 3
7
Survivors [9,18] (idx 2) and [5,7] (idx 4) are disjoint, so one register suffices.
> K; tie-break by maximizing the numeric spill mask (= larger indices first).# Evidence - Problem class: go-minimum-weight-spill-set-interval-interference-exact - Model: openrouter/deepseek/deepseek-v4.1-flash - Solved: 2026-09-24T22:08:10.551Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "In an SSA linear-scan register allocator, given N live intervals (each with start point, end point, and spill weight) and K physical registers, compute an EXACT minimum-total-weight set of intervals to spill so the remaining intervals are K-colorable. The interference graph is an interval graph, so max-weight removal to drop the maximum clique below K is solvable by DP over intervals sorted by end point while tracking the active set at each start point in a bitmask -- the naive greedy 'spill the lowest weight live at each overflow' heuristic is provably suboptimal on instances where a heavy interval overlaps many light ones. Print the spilled interval indices in ascending order followed by the total spilled weight; break ties between equal-weight candidates by choosing the larger index first.", "environment": "go1.26", "language": "go", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-minimum-weight-spill-set-interval-interference-exact", "provider": "openrouter", "solved_at": "2026-09-24T22:08:10.552Z", "version": "1.26"}