← Home
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"sort"
)

func main() {
	input, _ := io.ReadAll(os.Stdin)
	pos := 0

	nextInt := func() int {
		for pos < len(input) && input[pos] <= ' ' {
			pos++
		}
		if pos >= len(input) {
			return 0
		}
		res := 0
		for pos < len(input) && input[pos] > ' ' {
			res = res*10 + int(input[pos]-'0')
			pos++
		}
		return res
	}

	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()

	t := nextInt()
	if t == 0 {
		return
	}

	for tc := 0; tc < t; tc++ {
		n := nextInt()
		m := nextInt()

		a := make([]int, n*m)
		for i := 0; i < n*m; i++ {
			a[i] = nextInt()
		}

		sortedIdx := make([]int, n)
		for i := 0; i < n; i++ {
			sortedIdx[i] = i
		}

		sort.Slice(sortedIdx, func(i, j int) bool {
			return a[sortedIdx[i]*m+0] < a[sortedIdx[j]*m+0]
		})

		sufMax := make([]int, n*m)
		sufMin := make([]int, n*m)

		for i := 0; i < n; i++ {
			row := sortedIdx[i]
			sufMax[i*m+m-1] = a[row*m+m-1]
			sufMin[i*m+m-1] = a[row*m+m-1]
			for j := m - 2; j >= 0; j-- {
				val := a[row*m+j]
				if val > sufMax[i*m+j+1] {
					sufMax[i*m+j] = val
				} else {
					sufMax[i*m+j] = sufMax[i*m+j+1]
				}
				if val < sufMin[i*m+j+1] {
					sufMin[i*m+j] = val
				} else {
					sufMin[i*m+j] = sufMin[i*m+j+1]
				}
			}
		}

		prefMax := make([]int, n)
		prefMin := make([]int, n)
		for i := 0; i < n; i++ {
			row := sortedIdx[i]
			prefMax[i] = a[row*m+0]
			prefMin[i] = a[row*m+0]
		}

		topLmax := make([]int, n)
		topRmin := make([]int, n)
		botLmin := make([]int, n)
		botRmax := make([]int, n)

		found := false
		ansP := 0
		ansK := 0

		for k := 0; k < m-1; k++ {
			topLmax[0] = prefMax[0]
			topRmin[0] = sufMin[0*m+k+1]
			for i := 1; i < n; i++ {
				if prefMax[i] > topLmax[i-1] {
					topLmax[i] = prefMax[i]
				} else {
					topLmax[i] = topLmax[i-1]
				}
				if sufMin[i*m+k+1] < topRmin[i-1] {
					topRmin[i] = sufMin[i*m+k+1]
				} else {
					topRmin[i] = topRmin[i-1]
				}
			}

			botLmin[n-1] = prefMin[n-1]
			botRmax[n-1] = sufMax[(n-1)*m+k+1]
			for i := n - 2; i >= 0; i-- {
				if prefMin[i] < botLmin[i+1] {
					botLmin[i] = prefMin[i]
				} else {
					botLmin[i] = botLmin[i+1]
				}
				if sufMax[i*m+k+1] > botRmax[i+1] {
					botRmax[i] = sufMax[i*m+k+1]
				} else {
					botRmax[i] = botRmax[i+1]
				}
			}

			for p := 0; p < n-1; p++ {
				if topLmax[p] < botLmin[p+1] && topRmin[p] > botRmax[p+1] {
					found = true
					ansP = p
					ansK = k
					break
				}
			}

			if found {
				break
			}

			if k < m-2 {
				for i := 0; i < n; i++ {
					row := sortedIdx[i]
					val := a[row*m+k+1]
					if val > prefMax[i] {
						prefMax[i] = val
					}
					if val < prefMin[i] {
						prefMin[i] = val
					}
				}
			}
		}

		if found {
			out.WriteString("YES\n")
			colors := make([]byte, n)
			for i := 0; i <= ansP; i++ {
				colors[sortedIdx[i]] = 'B'
			}
			for i := ansP + 1; i < n; i++ {
				colors[sortedIdx[i]] = 'R'
			}
			out.Write(colors)
			out.WriteString(fmt.Sprintf(" %d\n", ansK+1))
		} else {
			out.WriteString("NO\n")
		}
	}
}