← Home
```go
package main

import (
	"bufio"
	"container/heap"
	"fmt"
	"os"
	"strconv"
)

// IO setup
var scanner *bufio.Scanner
var writer *bufio.Writer

func init() {
	scanner = bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	// Default buffer size is sufficient for integer tokens
	writer = bufio.NewWriter(os.Stdout)
}

func nextInt() int {
	scanner.Scan()
	val, _ := strconv.Atoi(scanner.Text())
	return val
}

// Max Heap for processing values in decreasing order
type IntHeap []int

func (h IntHeap) Len() int           { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] > h[j] } // Max Heap
func (h IntHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }

func (h *IntHeap) Push(x interface{}) {
	*h = append(*h, x.(int))
}

func (h *IntHeap) Pop() interface{} {
	old := *h
	n := len(old)
	x := old[n-1]
	*h = old[0 : n-1]
	return x
}

func main() {
	defer writer.Flush()

	n := nextInt()
	m := nextInt()

	// Store computer requirements: val -> list of indices (0-based)
	comps := make(map[int][]int)
	for i := 0; i < n; i++ {
		p := nextInt()
		comps[p] = append(comps[p], i)
	}

	// Sockets: val -> buckets of (index) by cost.
	// Max cost is around 30 for 10^9. Size 33 is safe.
	sockets := make(map[int]*[33][]int)

	// Heap to track active values
	pq := &IntHeap{}
	heap.Init(pq)
	inHeap := make(map[int]bool)

	addToHeap := func(val int) {
		if !inHeap[val] {
			heap.Push(pq, val)
			inHeap[val] = true
		}
	}

	// Read sockets and populate initial state
	for i := 0; i < m; i++ {
		s := nextInt()
		if sockets[s] == nil {
			sockets[s] = new([33][]int)
			addToHeap(s)
		}
		// Initial cost is 0
		sockets[s][0] = append(sockets[s][0], i)
	}

	// Ensure all computer values are in the heap
	for p := range comps {
		addToHeap(p)
	}

	// Result storage
	matchCount := 0
	totalAdapters := 0
	adapterCounts := make([]int, m)    // Stores adapter usage for each socket
	compConnectedTo := make([]int, n) // Stores socket index (1-based) for each computer

	// Process values from largest to smallest
	for pq.Len() > 0 {
		curr := heap.Pop(pq).(int)

		// 1. Try to match computers at this power level
		if compList, ok := comps[curr]; ok {
			sockBuckets := sockets[curr]
			if sockBuckets != nil {
				// Iterate through all computers needing 'curr' power
				for _, compID := range compList {
					// Find the available socket with the minimum accumulated cost
					matched := false
					for cost := 0; cost < 33; cost++ {
						if len(sockBuckets[cost]) > 0 {
							// Use this socket
							listLen := len(sockBuckets[cost])
							sockID := sockBuckets[cost][listLen-1]
							sockBuckets[cost] = sockBuckets[cost][:listLen-1]

							// Record the match
							matchCount++
							totalAdapters += cost
							adapterCounts[sockID] = cost
							compConnectedTo[compID] = sockID + 1 // Output 1-based index
							matched = true
							break
						}
					}
					// If we couldn't match this computer, we can't match it at all (needs exact power)
					// However, we continue to try matching other computers at this level with remaining sockets
					if !matched {
						// Optimization: if no sockets exist at all, we can stop checking for this value
						empty := true
						for c := 0; c < 33; c++ {
							if len(sockBuckets[c]) > 0 {
								empty = false
								break
							}
						}
						if empty {
							break
						}
					}
				}
			}
		}

		// 2. Move remaining sockets to the next power level: ceil(curr / 2)
		if curr == 1 {
			// Cannot reduce power below 1
			delete(sockets, curr)
			continue
		}

		sockBuckets := sockets[curr]
		// If no sockets at this level, nothing to move
		if sockBuckets == nil {
			continue
		}

		// Check if there are any sockets left to move
		anySocket := false
		for c := 0; c < 33; c++ {
			if len(sockBuckets[c]) > 0 {
				anySocket = true
				break
			}
		}

		if anySocket {
			nextVal := (curr + 1) / 2
			
			if sockets[nextVal] == nil {
				sockets[nextVal] = new([33][]int)
				addToHeap(nextVal)
			}
			nextBuckets := sockets[nextVal]

			// Transfer sockets, incrementing their cost by 1
			// cost c at curr becomes cost c+1 at nextVal
			for c := 0; c < 32; c++ {
				if len(sockBuckets[c]) > 0 {
					nextBuckets[c+1] = append(nextBuckets[c+1], sockBuckets[c]...)
				}
			}
		}
		
		// Clean up processed level to free memory
		delete(sockets, curr)
	}

	// Output results
	fmt.Fprintf(writer, "%d %d\n", matchCount, totalAdapters)

	for i := 0; i < m; i++ {
		if i > 0 {
			writer.WriteByte(' ')
		}
		fmt.Fprint(writer, adapterCounts[i])
	}
	writer.WriteByte('\n')

	for i := 0; i < n; i++ {
		if i > 0 {
			writer.WriteByte(' ')
		}
		fmt.Fprint(writer, compConnectedTo[i])
	}
	writer.WriteByte('\n')
}
```