type subcubes map[cuboid]int
func solveSecond(cbs []cuboid) int {
	m := subcubes{}
	for _, cube := range cbs {
		subMap := subcubes{}
		for orig := range m {
			ovrlp := overlap(cube, orig)
			if ovrlp.state == "noop" {
				continue
			}
			// do not count repeatedly the overlapping part
			// m[orig] can be 0, -1 and 1.
			// 0 means it was an "off" state
			// if it was 1, now we change it to -1, so adding a new cube with
			// state = "on" will change it to 0.
			subMap[ovrlp] -= m[orig]
		}
		if cube.state == "on" {
			subMap[cube] += 1
		}
		for c := range subMap {
			m[c] += subMap[c]
		}
	}
	var sum int
	for cube, v := range m {
		sum += cube.size() * v
	}
	return sum
}
func (c cuboid) size() int {
	return (c.xmax - c.xmin + 1) * (c.ymax - c.ymin + 1) * (c.zmax - c.zmin + 1)
}
func overlap(first, second cuboid) cuboid {
	// return none, if there is no overlap in one of the dimensions
	if first.xmax < second.xmin || second.xmax < first.xmin ||
		first.ymax < second.ymin || second.ymax < first.ymin ||
		first.zmax < second.zmin || second.zmax < first.zmin {
		return cuboid{state: "noop"}
	}
	return cuboid{"",
		max(first.xmin, second.xmin), min(first.xmax, second.xmax),
		max(first.ymin, second.ymin), min(first.ymax, second.ymax),
		max(first.zmin, second.zmin), min(first.zmax, second.zmax),
	}
}