← Home
```go
package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
	"strconv"
	"strings"
)

type rangePair struct {
	start uint32
	end   uint32
}

type Subnet struct {
	ip   uint32
	mask int
}

type node struct {
	children [2]*node
	force_req bool
	force_forb bool
}

func newNode() *node {
	return &node{}
}

func insert(root *node, base uint32, mask int, isReq bool) {
	cur := root
	val := base
	for d := 0; d < mask; d++ {
		bit := (val >> (31 - d)) & 1
		if cur.children[bit] == nil {
			cur.children[bit] = newNode()
		}
		cur = cur.children[bit]
	}
	if isReq {
		cur.force_req = true
	} else {
		cur.force_forb = true
	}
}

func build(n *node, val uint32, depth int) (bool, bool, int, []Subnet) {
	if n == nil {
		return false, false, 0, nil
	}
	lreq, lforb, lnum, lsubs := build(n.children[0], (val<<1)|uint32(0), depth+1)
	rreq, rforb, rnum, rsubs := build(n.children[1], (val<<1)|uint32(1), depth+1)
	hreq := n.force_req || lreq || rreq
	hforb := n.force_forb || lforb || rforb
	if !hreq {
		return hreq, hforb, 0, nil
	}
	if !hforb {
		b := val << (32 - depth)
		m := depth
		return hreq, hforb, 1, []Subnet{{b, m}}
	}
	num := lnum + rnum
	var subs []Subnet
	subs = append(subs, lsubs...)
	subs = append(subs, rsubs...)
	return hreq, hforb, num, subs
}

func decompose(s uint32, e uint32) []Subnet {
	var res []Subnet
	pos := uint64(s)
	ee := uint64(e)
	for pos <= ee {
		maxb := 0
		limit := ee - pos + 1
		for b := 0; b <= 32; b++ {
			sz := uint64(1) << uint64(b)
			if sz > limit {
				break
			}
			if pos%sz == 0 {
				maxb = b
			}
		}
		sz := uint64(1) << uint64(maxb)
		base := uint32(pos)
		masklen := 32 - maxb
		res = append(res, Subnet{base, masklen})
		pos += sz
	}
	return res
}

func mergeRanges(ranges []rangePair) []rangePair {
	if len(ranges) == 0 {
		return nil
	}
	sort.Slice(ranges, func(i, j int) bool { return ranges[i].start < ranges[j].start })
	var merged []rangePair
	merged = append(merged, ranges[0])
	for i := 1; i < len(ranges); i++ {
		last := &merged[len(merged)-1]
		if last.end >= ranges[i].start {
			if last.end < ranges[i].end {
				last.end = ranges[i].end
			}
		} else {
			merged = append(merged, ranges[i])
		}
	}
	return merged
}

func hasOverlap(black, white []rangePair) bool {
	i, j := 0, 0
	for i < len(black) && j < len(white) {
		if black[i].end < white[j].start {
			i++
			continue
		}
		if white[j].end < black[i].start {
			j++
			continue
		}
		return true
	}
	return false
}

func parseIP(ipstr string) uint32 {
	parts := strings.Split(ipstr, ".")
	a, _ := strconv.Atoi(parts[0])
	b, _ := strconv.Atoi(parts[1])
	c, _ := strconv.Atoi(parts[2])
	d, _ := strconv.Atoi(parts[3])
	return uint32(a<<24 | b<<16 | c<<8 | d)
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Scan()
	n, _ := strconv.Atoi(scanner.Text())
	var blacks []rangePair
	var whites []rangePair
	for i := 0; i < n; i++ {
		scanner.Scan()
		line := scanner.Text()
		sign := line[0]
		substr := line[1:]
		var ipstr string
		x := 32
		if strings.Contains(substr, "/") {
			parts := strings.Split(substr, "/")
			ipstr = parts[0]
			x, _ = strconv.Atoi(parts[1])
		} else {
			ipstr = substr
		}
		ip := parseIP(ipstr)
		var start, end uint32
		start = ip
		if x == 0 {
			start = 0
			end = 4294967295
		} else {
			size := uint32(1) << (32 - x)
			end = start + size - 1
		}
		if sign == '-' {
			blacks = append(blacks, rangePair{start, end})
		} else {
			whites = append(whites, rangePair{start, end})
		}
	}
	mblack := mergeRanges(blacks)
	mwhite := mergeRanges(whites)
	if hasOverlap(mblack, mwhite) {
		fmt.Println(-1)
		return
	}
	root := newNode()
	for _, r := range mblack {
		for _, sub := range decompose(r.start, r.end) {
			insert(root, sub.ip, sub.mask, true)
		}
	}
	for _, r := range mwhite {
		for _, sub := range decompose(r.start, r.end) {
			insert(root, sub.ip, sub.mask, false)
		}
	}
	_, _, num, subs := build(root, 0, 0)
	fmt.Println(num)
	for _, sub := range subs {
		a := sub.ip >> 24
		b := (sub.ip >> 16) & 255
		c := (sub.ip >> 8) & 255
		d := sub.ip & 255
		if sub.mask == 32 {
			fmt.Printf("%d.%d.%d.%d\n", a, b, c, d)
		} else {
			fmt.Printf("%d.%d.%d.%d/%d\n", a, b, c, d, sub.mask)
		}
	}
}
```