← Home
```go
package main

import (
	"fmt"
	"sort"
)

func main() {
	var n, k int
	fmt.Scan(&n, &k)

	prices := make([]int, n)
	types := make([]int, n)
	for i := 0; i < n; i++ {
		fmt.Scan(&prices[i], &types[i])
	}

	// indices sorted by price descending
	indices := make([]int, n)
	for i := 0; i < n; i++ {
		indices[i] = i
	}
	sort.Slice(indices, func(a, b int) bool {
		return prices[indices[a]] > prices[indices[b]]
	})

	// Separate stools and pencils in sorted order (descending price)
	var stools []int
	var pencils []int
	for _, idx := range indices {
		if types[idx] == 1 {
			stools = append(stools, idx)
		} else {
			pencils = append(pencils, idx)
		}
	}

	// Strategy: We have k carts. We want to maximize discounts.
	// Each cart with at least one stool gets 50% off the cheapest item in that cart.
	// To maximize total discount, we want to maximize the sum of the cheapest items in carts that contain stools.
	// 
	// Key insight: Sort all items by price descending. We can create up to min(k, len(stools)) carts with stools.
	// For each such cart, the discount applies to the cheapest item. To maximize the discount on expensive items,
	// we want each stool-cart to have its cheapest item be as expensive as possible.
	//
	// Greedy approach: sort items descending. Assign items to carts greedily.
	// We can have at most min(k, len(stools)) carts with discounts.
	// For each discount cart, we want exactly one stool and possibly one pencil (or just the stool).
	// Actually, we want the minimum item in the cart to be as large as possible.
	//
	// Better approach: We have stools sorted desc and pencils sorted desc.
	// We can form up to min(k, len(stools)) "discount groups". Each discount group has one stool.
	// To maximize the cheapest item in each group, pair the most expensive pencils with stools of similar or higher price.
	// Actually, pair each stool with at most one pencil, and the discount is on the min of the two.
	// If we have s stools and p pencils, and k carts:
	// - We must use exactly k carts, none empty.
	// - If s >= k: put at least one stool per cart. Extra stools go into existing carts.
	//   Each cart has a stool so discount on cheapest. Put all pencils into the cart with the most expensive stool
	//   (or distribute to maximize discounts). Actually if all carts have stools, discount is on cheapest item per cart.
	//   We want to maximize sum of min-items. Put pencils into carts where they won't reduce the min too much.
	//   Best: put all pencils into one cart (the one with the cheapest stool won't matter much).
	//   Actually we want pencils in carts where the stool is cheaper than the pencil, so pencil doesn't reduce min.

	// This is complex. Let me think about it differently with a known greedy:
	// Sort all items descending. Form groups: first k items each go into separate carts (one item each).
	// Remaining items go into the last cart (cart k). But we need to optimize discounts.
	
	// Actually, a cleaner known approach for this problem:
	// Sort all items descending by price. Take groups of items. The first k-1 groups have size 1 or 2,
	// and the last group has the rest. In each group that contains a stool, the cheapest item gets 50% off.
	// We want to maximize total discount = sum of cheapest items in groups with stools / 2.

	// Let me try: merge stools and pencils sorted descending. Greedily form k groups from the top.
	// Each group: if next item is a stool, take it alone (discount = price/2). Or pair it with next pencil if beneficial.
	// If next is pencil, take it alone (no discount) or pair with a stool.

	// This needs DP. Let me use DP.
	// dp[i][j] = max discount using first i stools and j pencils to fill some carts.
	// Actually, let me just try all possible groupings via DP on sorted items.

	// Simpler: sort all items desc. We need to partition into k non-empty groups (consecutive in sorted order).
	// The discount per group = cheapest_item/2 if group contains a stool, else 0.
	// We want to maximize total discount. The cheapest item in a consecutive group is the last one.

	// dp[i][j] = max discount partitioning first i items into j groups
	// This is O(n^2 * k) which is fine for n,k <= 1000.

	allItems := make([]int, n)
	copy(allItems, indices)
	// allItems is sorted descending by price

	hasStool := make([][]bool, n+1)
	for i := 0; i <= n; i++ {
		hasStool[i] = make([]bool, n+1)
	}
	// hasStool[l][r] = true if items allItems[l..r-1] contain a stool
	// Precompute prefix count of stools
	stoolPrefix := make([]int, n+1)
	for i := 0; i < n; i++ {
		stoolPrefix[i+1] = stoolPrefix[i]
		if types[allItems[i]] == 1 {
			stoolPrefix[i+1]++
		}
	}

	stoolInRange := func(l, r int) bool { // [l, r) 
		return stoolPrefix[r]-stoolPrefix[l] > 0
	}

	// dp[i][j] = max total discount when first i items (sorted desc) are split into j non-empty consecutive groups
	// Transition: dp[i][j] = max over l in [j-1, i-1] of dp[l][j-1] + discount(l, i)
	// discount(l, i) = prices[allItems[i-1]]/2 if stoolInRange(l, i), else 0
	// (because items are sorted desc, cheapest in group [l..i-1] is allItems[i-1])

	const NEG_INF = int64(-1e18)

	dp := make([][]int64, n+1)
	parent := make([][]int, n+1) // for reconstruction
	for i := 0; i <= n; i++ {
		dp[i] = make([]int64, k+1)
		parent[i] = make([]int, k+1)
		for j := 0; j <= k; j++ {
			dp[i][j] = NEG_INF
			parent[i][j] = -1
		}
	}
	dp[0][0] = 0

	for j := 1; j <= k; j++ {
		for i := j; i <= n; i++ {
			for l := j - 1; l < i; l++ {
				if dp[l][j-1] == NEG_INF {
					continue
				}
				discount := int64(0)
				if stoolInRange(l, i) {
					discount = int64(prices[allItems[i-1]])
				}
				val := dp[l][j-1] + discount
				if val > dp[i][j] {
					dp[i][j] = val
					parent[i][j] = l
				}
			}
		}
	}

	// Reconstruct groups
	groups := make([][]int, k)
	pos := n
	for j := k; j >= 1; j-- {
		l := parent[pos][j]
		group := []int{}
		for idx := l; idx < pos; idx++ {
			group = append(group, allItems[idx])
		}
		groups[j-1] = group
		pos = l
	}

	// Compute total price
	totalPrice := int64(0)
	for i := 0; i < n; i++ {
		totalPrice += int64(prices[i]) * 2
	}
	// discount is dp[n][k], which is sum of cheapest items in groups with stools
	// actual saving = dp[n][k] / 2 (in terms of original prices)
	// Let's compute in halves to avoid floating point
	// total in half-units = sum(prices)*2, discount = dp[n][k]
	totalHalf := totalPrice - dp[n][k]

	fmt.Printf("%d.%d\n", totalHalf/2, (totalHalf%2)*5)

	for i := 0; i < k; i++ {
		fmt.Print(len(groups[i]))
		for _, idx := range groups[i] {
			fmt.Printf(" %d", idx+1)
		}
		fmt.Println()
	}
}
```