import java.io.*
import java.util.*
import kotlin.math.*
//solves first version of F
fun main(){
	val f = BufferedReader(InputStreamReader(System.`in`))

	for(q in 1..f.readLine().toInt()){
		val n = f.readLine().toInt()

		val adj = Array(n+1){mutableListOf<Int>()}

		for(k in 2..n){
			val (a,b) = f.readLine().split(" ").map{it.toInt()}
			adj[a].add(b)
			adj[b].add(a)
		}

		//get length of path
		val sjq1 = StringJoiner(" ")
		sjq1.add("? $n")
		for(k in 1..n){
			sjq1.add("$k")
		}

		println(sjq1)
		System.out.flush()

		val (xq1,dq1) = f.readLine().split(" ").map{it.toInt()}

		val length = dq1+1

		println("? 1 1") //get depth of peak
		System.out.flush()

		val (xq2,dq2) = f.readLine().split(" ").map{it.toInt()}

		val depthofpeak = dq2-(dq1-1)-1
		println("$length $depthofpeak")
		val depths = IntArray(n+1)
		val parents = IntArray(n+1)
		val depthset = Array(n){hashSetOf<Int>()}
		depths[1] = 0
		var maxdepth = 0
		fun getdepths(v : Int, p : Int){
			parents[v] = p
			depthset[depths[v]].add(v)
			maxdepth = max(maxdepth,depths[v])

			for(nei in adj[v]){
				if(nei == p) continue
				depths[nei] = depths[v]+1
				getdepths(nei,v)
			}

		}
		getdepths(1,-1)
		//println(depths.joinToString(" "))
		//find deepest node with same d value as dq1
		var l = depthofpeak
		var r = maxdepth
		var ans = -1

		while(l <= r){
			val mid = l + (r-l)/2

			//println("$l $r")
			//query
			val sjq = StringJoiner(" ")
			sjq.add("? ${depthset[mid].size}")
			for(i in depthset[mid]){
				sjq.add("$i")
			}
			println(sjq)
			System.out.flush()
			val (xq,dq) = f.readLine().split(" ").map{it.toInt()}

			if(dq == dq1){
				ans = xq
				l = mid+1
			} else {
				r = mid-1
			}
		}

		//ans is one of the nodes

		val nogo = HashSet<Int>()
		var i = ans
		while(depths[i] != depthofpeak){
			nogo.add(i)
			i = parents[i]
		}
		val pathpeak = i
		val otherdepth = length - (depths[ans] - depthofpeak) + depthofpeak -1

		//println("$pathpeak $otherdepth")

		val finalqset = HashSet<Int>()

		fun finaldfs(v : Int){
			if(depths[v] == otherdepth) finalqset.add(v)

			for(nei in adj[v]){
				if(nei == parents[v] || nogo.contains(nei)) continue
				finaldfs(nei)

			}
		}
		finaldfs(pathpeak)
		val sjfinal = StringJoiner(" ")
		sjfinal.add("? ${finalqset.size}")

		for(k in finalqset){
			sjfinal.add("$k")
		}

		println(sjfinal)
		System.out.flush()

		val (xqfinal,dqfinal) = f.readLine().split(" ").map{it.toInt()}

		println("! $ans $xqfinal")
		System.out.flush()

		val verdict = f.readLine()

	}
}


import java.io.BufferedReader
import java.util.*

fun main() {
    val br = System.`in`.bufferedReader()
    val t = br.readInt()
    val qNodes = mutableListOf<Int>()
    fun query(): Pair<Int, Int> {
        if(qNodes.size == 0){
            return Pair(-1, Int.MAX_VALUE)
        }
        println("? %d %s".format(qNodes.size, qNodes.joinToString(" ")))
        qNodes.clear()
        val node = br.readInt()
        val dist = br.readInt()
        return Pair(node - 1, dist)
    }
    repeat(t) {
        val n = br.readInt()
        val cons = Array(n) { mutableListOf<Int>() }
        repeat(n - 1) {
            val u = br.readInt() - 1
            val v = br.readInt() - 1
            cons[u].add(v)
            cons[v].add(u)
        }
        for (x in 1..n) {
            qNodes.add(x)
        }
        val (node, dist) = query()
        val queue: Queue<Int> = ArrayDeque()
        val dists = IntArray(n) { -1 }
        queue += node
        dists[node] = 0
        while (queue.isNotEmpty()) {
            val cur = queue.poll()
            for (adj in cons[cur]) {
                if (dists[adj] == -1) {
                    dists[adj] = dists[cur] + 1
                    queue += adj
                }
            }
        }
        var last = -1
        var high = dist + 1
        var low = ((dist + 1) shr 1)
        var mid = (high + low) shr 1
        while (low != high) {
            for (x in 0 until n) {
                if (dists[x] == mid) {
                    qNodes.add(x + 1)
                }
            }
            val (newNode, newDist) = query()
            if (newDist == dist) {
                last = newNode
                low = mid + 1
            } else {
                high = mid
            }
            mid = (high + low) shr 1
        }
        val dists2 = IntArray(n) { -1 }
        queue += last
        dists2[last] = 0
        while (queue.isNotEmpty()) {
            val cur = queue.poll()
            for (adj in cons[cur]) {
                if (dists2[adj] == -1) {
                    dists2[adj] = dists2[cur] + 1
                    queue += adj
                }
            }
        }
        val other = if (dist - dists[last] == 0) {
            node
        } else {
            for (x in 0 until n) {
                if (dists2[x] == dist && dists[x] == dist - dists[last]) {
                    qNodes += x + 1
                }
            }
            query().first
        }

        println("! %d %d".format(last + 1, other + 1))
        br.readLine()
    }
}

private const val SPACE_INT = ' '.toInt()
private const val ZERO_INT = '0'.toInt()
private const val NL_INT = '\n'.toInt()

@Suppress("DuplicatedCode")
private fun BufferedReader.readInt(): Int {
    var ret = read()
    while (ret <= SPACE_INT) {
        ret = read()
    }
    val neg = ret == '-'.toInt()
    if (neg) {
        ret = read()
    }
    ret -= ZERO_INT
    var read = read()
    while (read >= ZERO_INT) {
        ret *= 10
        ret += read - ZERO_INT
        read = read()
    }

    while (read <= SPACE_INT && read != -1 && read != NL_INT) {
        mark(1)
        read = read()
    }
    if (read > SPACE_INT) {
        reset()
    }
    return if (neg) -ret else ret
}


import java.io.BufferedReader
import java.util.*
import kotlin.system.exitProcess

fun main() {
    val br = System.`in`.bufferedReader()
    val t = br.readInt()
    val qNodes = mutableListOf<Int>()
    fun query(): Pair<Int, Int> {
        println("? %d %s".format(qNodes.size, qNodes.joinToString(" ")))
        qNodes.clear()
        return Pair(br.readInt() - 1, br.readInt())
    }
    repeat(t) {
        val n = br.readInt()
        val cons = Array(n) { mutableListOf<Int>() }
        repeat(n - 1) {
            val u = br.readInt() - 1
            val v = br.readInt() - 1
            cons[u].add(v)
            cons[v].add(u)
        }
        for (x in 1..n) {
            qNodes.add(x)
        }
        val (node, dist) = query()
        val queue: Queue<Int> = ArrayDeque()
        val dists = IntArray(n) { -1 }
        queue += node
        dists[node] = 0
        while (queue.isNotEmpty()) {
            val cur = queue.poll()
            for (adj in cons[cur]) {
                if (dists[adj] == -1) {
                    dists[adj] = dists[cur] + 1
                    queue += adj
                }
            }
        }
        var last = -1
        var high = dist + 1
        var low = ((dist + 1) shr 1)
        var mid = (high + low) shr 1
        while (low != high) {
            for (x in 0 until n) {
                if (dists[x] == mid) {
                    qNodes.add(x + 1)
                }
            }
            val (newNode, newDist) = query()
            if (newDist == dist) {
                last = newNode
                low = mid + 1
            } else {
                high = mid
            }
            mid = (high + low) shr 1
        }
        val dists2 = IntArray(n) { -1 }
        queue += last
        dists2[last] = 0
        while (queue.isNotEmpty()) {
            val cur = queue.poll()
            for (adj in cons[cur]) {
                if (dists2[adj] == -1) {
                    dists2[adj] = dists2[cur] + 1
                    queue += adj
                }
            }
        }
        val other = if(dist - dists[last] == 0){
            node
        } else {
            for (x in 0 until n) {
                if (dists2[x] == dist && dists[x] == dist - dists[last]) {
                    qNodes += x + 1
                }
            }
            query().first
        }

        println("! %d %d".format(last + 1, other + 1))
        br.readLine()
    }
}

private const val SPACE_INT = ' '.toInt()
private const val ZERO_INT = '0'.toInt()
private const val NL_INT = '\n'.toInt()

@Suppress("DuplicatedCode")
private fun BufferedReader.readInt(): Int {
    var ret = read()
    while (ret <= SPACE_INT) {
        ret = read()
    }
    val neg = ret == '-'.toInt()
    if (neg) {
        ret = read()
    }
    ret -= ZERO_INT
    var read = read()
    while (read >= ZERO_INT) {
        ret *= 10
        ret += read - ZERO_INT
        read = read()
    }

    while (read <= SPACE_INT && read != -1 && read != NL_INT) {
        mark(1)
        read = read()
    }
    if (read > SPACE_INT) {
        reset()
    }
    return if (neg) -ret else ret
}


import java.io.BufferedReader
import java.util.*
import kotlin.system.exitProcess

fun main() {
    val br = System.`in`.bufferedReader()
    val t = br.readInt()
    val qNodes = mutableListOf<Int>()
    fun query(): Pair<Int, Int> {
        println("? %d %s".format(qNodes.size, qNodes.joinToString(" ")))
        qNodes.clear()
        return Pair(br.readInt() - 1, br.readInt())
    }
    repeat(t) {
        val n = br.readInt()
        val cons = Array(n) { mutableListOf<Int>() }
        repeat(n - 1) {
            val u = br.readInt() - 1
            val v = br.readInt() - 1
            cons[u].add(v)
            cons[v].add(u)
        }
        for (x in 1..n) {
            qNodes.add(x)
        }
        val (node, dist) = query()
        val queue: Queue<Int> = ArrayDeque()
        val dists = IntArray(n) { -1 }
        queue += node
        dists[node] = 0
        while (queue.isNotEmpty()) {
            val cur = queue.poll()
            for (adj in cons[cur]) {
                if (dists[adj] == -1) {
                    dists[adj] = dists[cur] + 1
                    queue += adj
                }
            }
        }
        var last = -1
        var high = dist + 1
        var low = ((dist + 1) shr 1)
        var mid = (high + low) shr 1
        while (low != high) {
            for (x in 0 until n) {
                if (dists[x] == mid) {
                    qNodes.add(x + 1)
                }
            }
            val (newNode, newDist) = query()
            if (newDist == dist) {
                last = newNode
                low = mid + 1
            } else {
                high = mid
            }
            mid = (high + low) shr 1
        }
        val dists2 = IntArray(n) { -1 }
        queue += last
        dists2[last] = 0
        while (queue.isNotEmpty()) {
            val cur = queue.poll()
            for (adj in cons[cur]) {
                if (dists2[adj] == -1) {
                    dists2[adj] = dists2[cur] + 1
                    queue += adj
                }
            }
        }
        val other = if(dist - dists[last] == 0){
            node
        } else {
            for (x in 0 until n) {
                if (dists2[x] == dist && dists[x] == dist - dists[last]) {
                    qNodes += x + 1
                }
            }
            query().first
        }

        println("! %d %d".format(last + 1, other + 1))
        if (br.readLine() != "Correct") {
            exitProcess(0)
        }
    }
}

private const val SPACE_INT = ' '.toInt()
private const val ZERO_INT = '0'.toInt()
private const val NL_INT = '\n'.toInt()

@Suppress("DuplicatedCode")
private fun BufferedReader.readInt(): Int {
    var ret = read()
    while (ret <= SPACE_INT) {
        ret = read()
    }
    val neg = ret == '-'.toInt()
    if (neg) {
        ret = read()
    }
    ret -= ZERO_INT
    var read = read()
    while (read >= ZERO_INT) {
        ret *= 10
        ret += read - ZERO_INT
        read = read()
    }

    while (read <= SPACE_INT && read != -1 && read != NL_INT) {
        mark(1)
        read = read()
    }
    if (read > SPACE_INT) {
        reset()
    }
    return if (neg) -ret else ret
}


import java.io.BufferedReader
import java.util.*
import kotlin.system.exitProcess

fun main() {
    val br = System.`in`.bufferedReader()
    val t = br.readInt()
    val qNodes = mutableListOf<Int>()
    fun query(): Pair<Int, Int> {
        println("? %d %s".format(qNodes.size, qNodes.joinToString(" ")))
        qNodes.clear()
        val node = br.readInt()
        val dist = br.readInt()
        if (node == -1) {
            exitProcess(0)
        }
        return Pair(node - 1, dist)
    }
    repeat(t) {
        val n = br.readInt()
        val cons = Array(n) { mutableListOf<Int>() }
        repeat(n - 1) {
            val u = br.readInt() - 1
            val v = br.readInt() - 1
            cons[u].add(v)
            cons[v].add(u)
        }
        for (x in 1..n) {
            qNodes.add(x)
        }
        val (node, dist) = query()
        val queue: Queue<Int> = ArrayDeque()
        val dists = IntArray(n) { -1 }
        queue += node
        dists[node] = 0
        while (queue.isNotEmpty()) {
            val cur = queue.poll()
            for (adj in cons[cur]) {
                if (dists[adj] == -1) {
                    dists[adj] = dists[cur] + 1
                    queue += adj
                }
            }
        }
        var last = -1
        var high = dist + 1
        var low = ((dist + 1) shr 1)
        var mid = (high + low) shr 1
        while (low != high) {
            for (x in 0 until n) {
                if (dists[x] == mid) {
                    qNodes.add(x + 1)
                }
            }
            val (newNode, newDist) = query()
            if (newDist == dist) {
                last = newNode
                low = mid + 1
            } else {
                high = mid
            }
            mid = (high + low) shr 1
        }
        val dists2 = IntArray(n) { -1 }
        queue += last
        dists2[last] = 0
        while (queue.isNotEmpty()) {
            val cur = queue.poll()
            for (adj in cons[cur]) {
                if (dists2[adj] == -1) {
                    dists2[adj] = dists2[cur] + 1
                    queue += adj
                }
            }
        }
        val other = if (dist - dists[last] == 0) {
            node
        } else {
            for (x in 0 until n) {
                if (dists2[x] == dist && dists[x] == dist - dists[last]) {
                    qNodes += x + 1
                }
            }
            query().first
        }

        println("! %d %d".format(last + 1, other + 1))
        br.readLine()
    }
}

private const val SPACE_INT = ' '.toInt()
private const val ZERO_INT = '0'.toInt()
private const val NL_INT = '\n'.toInt()

@Suppress("DuplicatedCode")
private fun BufferedReader.readInt(): Int {
    var ret = read()
    while (ret <= SPACE_INT) {
        ret = read()
    }
    val neg = ret == '-'.toInt()
    if (neg) {
        ret = read()
    }
    ret -= ZERO_INT
    var read = read()
    while (read >= ZERO_INT) {
        ret *= 10
        ret += read - ZERO_INT
        read = read()
    }

    while (read <= SPACE_INT && read != -1 && read != NL_INT) {
        mark(1)
        read = read()
    }
    if (read > SPACE_INT) {
        reset()
    }
    return if (neg) -ret else ret
}


import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author abacaba
 */
public class f {
    public static void main(String[] args) {
        FS in = new FS(System.in);
        PrintWriter out = new PrintWriter(System.out);

        int t = in.nextInt(); int c = 0; while(c++<t) {
//            out.print("Case #" + c + ": ");
            if(!new f().solve(in, out)) return;
        }

        out.close();
    }

    ArrayList<Integer>[] adj, nums;
    boolean[] vis;
    int[] par;

    void dfs(int ind, int d) {
        nums[d].add(ind);
        vis[ind] = true;
        for(int a : adj[ind]) if(!vis[a]) {
            dfs(a, d+1);
            par[a] = ind;
        }
    }

    boolean solve(FS in, PrintWriter out) {
        int n = in.nextInt();
        adj = new ArrayList[n];
        nums = new ArrayList[n];
        par = new int[n];
        vis = new boolean[n];
        Arrays.setAll(adj, i->new ArrayList<>());
        Arrays.setAll(nums, i->new ArrayList<>());

        for(int i = 1; i < n; i++) {
            int u = in.nextInt()-1;
            int v = in.nextInt()-1;
            adj[u].add(v);
            adj[v].add(u);
        }

        out.print("? " + n);
        for(int i = 1; i <= n; i++) out.print(" " + i);
        out.println();
        out.flush();

        int root = in.nextInt()-1;
        int DIST = in.nextInt();
        if(root == -2) return false;

        dfs(root, 0);

        int res = root;

        int curr = 0;
        for(int pow = 1<<9; pow > 0; pow >>= 1) {
            int tmp = curr+pow;
            if(tmp > DIST || nums[tmp].size() == 0) continue;
            out.print("? " + nums[tmp].size());
            for(int a : nums[tmp]) out.print(" " + (a+1));
            out.println();
            out.flush();
            int x = in.nextInt()-1;
            int d = in.nextInt();
            if(x == -2) return false;
            if(d == DIST) {
                curr = tmp;
                res = x;
            }
        }

        vis = new boolean[n];
        Arrays.setAll(nums, i->new ArrayList<>());
        dfs(res, 0);
        out.print("? " + nums[DIST].size());
        for(int a : nums[DIST]) out.print(" " + (a+1));
        out.println();
        out.flush();

        int x = in.nextInt()-1;
        int d = in.nextInt();
        if(x == -2) return false;
        out.println("! " + (res+1) + " " + (x+1));
        out.flush();

        return in.next().equals("Correct");
    }

    static class FS {
        BufferedReader in; StringTokenizer tk;
        public FS(InputStream st) {
            in = new BufferedReader(new InputStreamReader(st));
            tk = new StringTokenizer("");
        }

        public String next() {
            if(tk.hasMoreTokens()) return tk.nextToken();
            try { tk = new StringTokenizer(in.readLine()); } catch(Exception e) {}
            return next();
        }

        public int nextInt() { return Integer.parseInt(next()); }
        public long nextLong() { return Long.parseLong(next()); }
        public double nextDouble() { return Double.parseDouble(next()); }
    }
}


import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author abacaba
 */
public class f {
    public static void main(String[] args) {
        FS in = new FS(System.in);
        PrintWriter out = new PrintWriter(System.out);

        int t = in.nextInt(); int c = 0; while(c++<t) {
//            out.print("Case #" + c + ": ");
            if(!new f().solve(in, out)) return;
        }

        out.close();
    }

    ArrayList<Integer>[] adj, nums;
    boolean[] vis;
    int[] par;

    void dfs(int ind, int d) {
        nums[d].add(ind);
        vis[ind] = true;
        for(int a : adj[ind]) if(!vis[a]) {
            dfs(a, d+1);
            par[a] = ind;
        }
    }

    boolean solve(FS in, PrintWriter out) {
        int n = in.nextInt();
        adj = new ArrayList[n];
        nums = new ArrayList[n];
        par = new int[n];
        vis = new boolean[n];
        Arrays.setAll(adj, i->new ArrayList<>());
        Arrays.setAll(nums, i->new ArrayList<>());

        for(int i = 1; i < n; i++) {
            int u = in.nextInt()-1;
            int v = in.nextInt()-1;
            adj[u].add(v);
            adj[v].add(u);
        }

        out.print("? " + n);
        for(int i = 1; i <= n; i++) out.print(" " + i);
        out.println();
        out.flush();

        int root = in.nextInt()-1;
        int DIST = in.nextInt();
        if(root == -2) return false;

        dfs(root, 0);

        int res = root;

        int curr = 0;
        for(int pow = 1<<9; pow > 0; pow >>= 1) {
            int tmp = curr+pow;
            if(tmp > DIST) continue;
            out.print("? " + nums[tmp].size());
            for(int a : nums[tmp]) out.print(" " + (a+1));
            out.println();
            out.flush();
            int x = in.nextInt()-1;
            int d = in.nextInt();
            if(x == -2) return false;
            if(d == DIST) {
                curr = tmp;
                res = x;
            }
        }

        vis = new boolean[n];
        Arrays.setAll(nums, i->new ArrayList<>());
        dfs(res, 0);
        out.print("? " + nums[DIST].size());
        for(int a : nums[DIST]) out.print(" " + (a+1));
        out.println();
        out.flush();

        int x = in.nextInt()-1;
        int d = in.nextInt();
        if(x == -2) return false;
        out.println("! " + (res+1) + " " + (x+1));
        out.flush();

        return in.next().equals("Correct");
    }

    static class FS {
        BufferedReader in; StringTokenizer tk;
        public FS(InputStream st) {
            in = new BufferedReader(new InputStreamReader(st));
            tk = new StringTokenizer("");
        }

        public String next() {
            if(tk.hasMoreTokens()) return tk.nextToken();
            try { tk = new StringTokenizer(in.readLine()); } catch(Exception e) {}
            return next();
        }

        public int nextInt() { return Integer.parseInt(next()); }
        public long nextLong() { return Long.parseLong(next()); }
        public double nextDouble() { return Double.parseDouble(next()); }
    }
}


import java.io.*;
import java.util.*;

/*
polyakoff
*/

public class Main {

    static FastReader in;
    static PrintWriter out;
    static Random rand = new Random();
    static final int oo = (int) 2e9;
    static final long OO = (long) 4e18;
    static final int MOD = (int) 1e9 + 7;

    static int n, U, D, ans1, ans2;
    static ArrayList<Integer>[] g;
    static int[] par, dep;

    static void ask(ArrayList<Integer> toAsk) {
        out.print("? " + toAsk.size());
        for (int u : toAsk)
            out.print(" " + (u + 1));
        out.println();
        out.flush();
        U = in.nextInt() - 1;
        D = in.nextInt();
    }

    static void dfs(int u) {
        for (int v : g[u]) {
            if (par[v] == -1) {
                par[v] = u;
                dep[v] = dep[u] + 1;
                dfs(v);
            }
        }
    }

    static void solve() {
        n = in.nextInt();

        g = new ArrayList[n]; Arrays.setAll(g, i -> new ArrayList<>());
        for (int i = 0; i < n - 1; i++) {
            int u = in.nextInt() - 1;
            int v = in.nextInt() - 1;
            g[u].add(v);
            g[v].add(u);
        }

        ArrayList<Integer> toAsk = new ArrayList<>();
        for (int u = 0; u < n; u++)
            toAsk.add(u);

        ask(toAsk);

        int root = U;
        int len = D;

        par = new int[n]; Arrays.fill(par, -1);
        dep = new int[n];
        par[root] = root;
        dep[root] = 0;
        dfs(root);

        int maxDep = 0;
        for (int u = 0; u < n; u++)
            maxDep = Math.max(maxDep, dep[u]);

        int low = (len + 1) / 2 - 1, high = Math.min(len, maxDep);
        while (low < high) {
            int mid = (low + high + 1) / 2;

            toAsk.clear();
            for (int u = 0; u < n; u++) {
                if (dep[u] == mid)
                    toAsk.add(u);
            }

            ask(toAsk);

            if (D == len) {
                low = mid;
                ans1 = U;
            } else
                high = mid - 1;
        }

        int not = ans1;
        while (dep[not] != len - dep[ans1])
            not = par[not];

        toAsk.clear();
        for (int u = 0; u < n; u++) {
            if (dep[u] == len - dep[ans1] && u != not)
                toAsk.add(u);
        }

        if (toAsk.size() > 0) {
            ask(toAsk);
            ans2 = U;
        } else
            ans2 = root;

        out.println("! " + (ans1 + 1) + " " + (ans2 + 1));
        out.flush();
        if (!in.next().equals("Correct")) {
            out.flush();
            System.exit(0);
        }
//        assert in.next().equals("Correct");

    }

    public static void main(String[] args) throws FileNotFoundException {
        in = new FastReader(System.in);
//        in = new FastReader(new FileInputStream("sometext.txt"));
        out = new PrintWriter(System.out);
//        out = new PrintWriter(new FileOutputStream("output.txt"));

        int T = 1;
        T = in.nextInt();
        while (T-- > 0)
            solve();

//        Thread thread = new Thread(null, () -> {
//            solve();
//        }, "Main", 1 << 28);
//        thread.start();
//        try {
//            thread.join();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

//        out.flush();
        out.close();
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        FastReader(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        Integer nextInt() {
            return Integer.parseInt(next());
        }

        Long nextLong() {
            return Long.parseLong(next());
        }

        Double nextDouble() {
            return Double.parseDouble(next());
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(nextLine());
            }
            return st.nextToken();
        }

        String nextLine() {
            String s = "";
            try {
                s = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return s;
        }
    }

    static void dbg(Object... args) {
        for (Object arg : args)
            out.print(arg + " ");
        out.println();
    }

}


import java.io.*;
import java.util.*;

/*
polyakoff
*/

public class Main {

    static FastReader in;
    static PrintWriter out;
    static Random rand = new Random();
    static final int oo = (int) 2e9;
    static final long OO = (long) 4e18;
    static final int MOD = (int) 1e9 + 7;

    static int n, U, D, ans1, ans2;
    static ArrayList<Integer>[] g;
    static int[] par, dep;

    static void ask(ArrayList<Integer> toAsk) {
        out.print("? " + toAsk.size());
        for (int u : toAsk)
            out.print(" " + (u + 1));
        out.println();
        out.flush();
        U = in.nextInt() - 1;
        D = in.nextInt();
    }

    static void dfs(int u) {
        for (int v : g[u]) {
            if (par[v] == -1) {
                par[v] = u;
                dep[v] = dep[u] + 1;
                dfs(v);
            }
        }
    }

    static void solve() {
        n = in.nextInt();

        g = new ArrayList[n]; Arrays.setAll(g, i -> new ArrayList<>());
        for (int i = 0; i < n - 1; i++) {
            int u = in.nextInt() - 1;
            int v = in.nextInt() - 1;
            g[u].add(v);
            g[v].add(u);
        }

        ArrayList<Integer> all = new ArrayList<>();
        for (int u = 0; u < n; u++)
            all.add(u);

        ask(all);

        int root = U;
        int len = D;

        par = new int[n]; Arrays.fill(par, -1);
        dep = new int[n];
        par[root] = root;
        dep[root] = 0;
        dfs(root);

        ArrayList<Integer> lowLevel = new ArrayList<>();
        int maxDep = 0;
        for (int u = 0; u < n; u++)
            maxDep = Math.max(maxDep, dep[u]);
        int d = Math.min(len, maxDep);
        for (int u = 0; u < n; u++) {
            if (dep[u] == d)
                lowLevel.add(u);
        }

        ask(lowLevel);
        d = (D - len) / 2;
        ans1 = U;
        for (int i = 0; i < d; i++)
            ans1 = par[ans1];

        int not = ans1;
        while (dep[not] != len - dep[ans1])
            not = par[not];

        ArrayList<Integer> highLevel = new ArrayList<>();
        for (int u = 0; u < n; u++) {
            if (dep[u] == len - dep[ans1] && u != not)
                highLevel.add(u);
        }

        if (highLevel.size() == 0) {
            ans2 = root;
        } else {
            ask(highLevel);
            ans2 = U;
        }

        out.println("! " + (ans1 + 1) + " " + (ans2 + 1));
//        out.flush();

    }

    public static void main(String[] args) throws FileNotFoundException {
        in = new FastReader(System.in);
//        in = new FastReader(new FileInputStream("sometext.txt"));
        out = new PrintWriter(System.out);
//        out = new PrintWriter(new FileOutputStream("output.txt"));

        int T = 1;
        T = in.nextInt();
        while (T-- > 0)
            solve();

//        Thread thread = new Thread(null, () -> {
//            solve();
//        }, "Main", 1 << 28);
//        thread.start();
//        try {
//            thread.join();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

//        out.flush();
        out.close();
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        FastReader(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        Integer nextInt() {
            return Integer.parseInt(next());
        }

        Long nextLong() {
            return Long.parseLong(next());
        }

        Double nextDouble() {
            return Double.parseDouble(next());
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(nextLine());
            }
            return st.nextToken();
        }

        String nextLine() {
            String s = "";
            try {
                s = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return s;
        }
    }

    static void dbg(Object... args) {
        for (Object arg : args)
            out.print(arg + " ");
        out.println();
    }

}


import java.io.*;
import java.util.*;

/*
polyakoff
*/

public class Main {

    static FastReader in;
    static PrintWriter out;
    static Random rand = new Random();
    static final int oo = (int) 2e9;
    static final long OO = (long) 4e18;
    static final int MOD = (int) 1e9 + 7;

    static int n, U, D, ans1, ans2;
    static ArrayList<Integer>[] g;
    static int[] par, dep;

    static void ask(ArrayList<Integer> toAsk) {
        out.print("? " + toAsk.size());
        for (int u : toAsk)
            out.print(" " + (u + 1));
        out.println();
        out.flush();
        U = in.nextInt() - 1;
        D = in.nextInt();
    }

    static void dfs(int u) {
        for (int v : g[u]) {
            if (par[v] == -1) {
                par[v] = u;
                dep[v] = dep[u] + 1;
                dfs(v);
            }
        }
    }

    static void solve() {
        n = in.nextInt();

        g = new ArrayList[n]; Arrays.setAll(g, i -> new ArrayList<>());
        for (int i = 0; i < n - 1; i++) {
            int u = in.nextInt() - 1;
            int v = in.nextInt() - 1;
            g[u].add(v);
            g[v].add(u);
        }

        ArrayList<Integer> all = new ArrayList<>();
        for (int u = 0; u < n; u++)
            all.add(u);

        ask(all);

        int root = U;
        int len = D;

        par = new int[n]; Arrays.fill(par, -1);
        dep = new int[n];
        par[root] = root;
        dep[root] = 0;
        dfs(root);

        ArrayList<Integer> lowLevel = new ArrayList<>();
        int maxDep = 0;
        for (int u = 0; u < n; u++)
            maxDep = Math.max(maxDep, dep[u]);
        int d = Math.min(len, maxDep);
        for (int u = 0; u < n; u++) {
            if (dep[u] == d)
                lowLevel.add(u);
        }

        ask(lowLevel);
        d = (D - len) / 2;
        ans1 = U;
        for (int i = 0; i < d; i++)
            ans1 = par[ans1];

        int not = ans1;
        while (dep[not] != len - dep[ans1])
            not = par[not];

        ArrayList<Integer> highLevel = new ArrayList<>();
        for (int u = 0; u < n; u++) {
            if (dep[u] == len - dep[ans1] && u != not)
                highLevel.add(u);
        }

        if (highLevel.size() == 0) {
            ans2 = root;
        } else {
            ask(highLevel);
            ans2 = U;
        }

        out.println("! " + (ans1 + 1) + " " + (ans2 + 1));
        out.flush();
        in.next();

    }

    public static void main(String[] args) throws FileNotFoundException {
        in = new FastReader(System.in);
//        in = new FastReader(new FileInputStream("sometext.txt"));
        out = new PrintWriter(System.out);
//        out = new PrintWriter(new FileOutputStream("output.txt"));

        int T = 1;
        T = in.nextInt();
        while (T-- > 0)
            solve();

//        Thread thread = new Thread(null, () -> {
//            solve();
//        }, "Main", 1 << 28);
//        thread.start();
//        try {
//            thread.join();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

//        out.flush();
        out.close();
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        FastReader(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        Integer nextInt() {
            return Integer.parseInt(next());
        }

        Long nextLong() {
            return Long.parseLong(next());
        }

        Double nextDouble() {
            return Double.parseDouble(next());
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(nextLine());
            }
            return st.nextToken();
        }

        String nextLine() {
            String s = "";
            try {
                s = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return s;
        }
    }

    static void dbg(Object... args) {
        for (Object arg : args)
            out.print(arg + " ");
        out.println();
    }

}


import java.io.*;
import java.util.*;

/*
polyakoff
*/

public class Main {

    static FastReader in;
    static PrintWriter out;
    static Random rand = new Random();
    static final int oo = (int) 2e9;
    static final long OO = (long) 4e18;
    static final int MOD = (int) 1e9 + 7;

    static int n, U, D, ans1, ans2;
    static ArrayList<Integer>[] g;
    static int[] par, dep;

    static void ask(ArrayList<Integer> toAsk) {
        out.print("? " + toAsk.size());
        for (int u : toAsk)
            out.print(" " + (u + 1));
        out.println();
        out.flush();
        U = in.nextInt() - 1;
        D = in.nextInt();
    }

    static void dfs(int u) {
        for (int v : g[u]) {
            if (par[v] == -1) {
                par[v] = u;
                dep[v] = dep[u] + 1;
                dfs(v);
            }
        }
    }

    static void solve() {
        n = in.nextInt();

        out.println("LOL");
        out.flush();

        g = new ArrayList[n]; Arrays.setAll(g, i -> new ArrayList<>());
        for (int i = 0; i < n - 1; i++) {
            int u = in.nextInt() - 1;
            int v = in.nextInt() - 1;
            g[u].add(v);
            g[v].add(u);
        }

        ArrayList<Integer> all = new ArrayList<>();
        for (int u = 0; u < n; u++)
            all.add(u);

        ask(all);

        int root = U;
        int len = D;

        par = new int[n]; Arrays.fill(par, -1);
        dep = new int[n];
        par[root] = root;
        dep[root] = 0;
        dfs(root);

        ArrayList<Integer> lowLevel = new ArrayList<>();
        int maxDep = 0;
        for (int u = 0; u < n; u++)
            maxDep = Math.max(maxDep, dep[u]);
        int d = Math.min(len, maxDep);
        for (int u = 0; u < n; u++) {
            if (dep[u] == d)
                lowLevel.add(u);
        }

        ask(lowLevel);
        d = (D - len) / 2;
        ans1 = U;
        for (int i = 0; i < d; i++)
            ans1 = par[ans1];

        int not = ans1;
        while (dep[not] != len - dep[ans1])
            not = par[not];

        ArrayList<Integer> highLevel = new ArrayList<>();
        for (int u = 0; u < n; u++) {
            if (dep[u] == len - dep[ans1] && u != not)
                highLevel.add(u);
        }

        if (highLevel.size() == 0) {
            ans2 = root;
        } else {
            ask(highLevel);
            ans2 = U;
        }

        out.println("! " + (ans1 + 1) + " " + (ans2 + 1));
        out.flush();
        if (!in.next().equals("Correct")) {
            out.flush();
            System.exit(0);
        }

    }

    public static void main(String[] args) throws FileNotFoundException {
        in = new FastReader(System.in);
//        in = new FastReader(new FileInputStream("sometext.txt"));
        out = new PrintWriter(System.out);
//        out = new PrintWriter(new FileOutputStream("output.txt"));

        int T = 1;
        T = in.nextInt();
        while (T-- > 0)
            solve();

//        Thread thread = new Thread(null, () -> {
//            solve();
//        }, "Main", 1 << 28);
//        thread.start();
//        try {
//            thread.join();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

//        out.flush();
        out.close();
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        FastReader(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        Integer nextInt() {
            return Integer.parseInt(next());
        }

        Long nextLong() {
            return Long.parseLong(next());
        }

        Double nextDouble() {
            return Double.parseDouble(next());
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(nextLine());
            }
            return st.nextToken();
        }

        String nextLine() {
            String s = "";
            try {
                s = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return s;
        }
    }

    static void dbg(Object... args) {
        for (Object arg : args)
            out.print(arg + " ");
        out.println();
    }

}


import java.io.*;
import java.util.*;

/*
polyakoff
*/

public class Main {

    static FastReader in;
    static PrintWriter out;
    static Random rand = new Random();
    static final int oo = (int) 2e9;
    static final long OO = (long) 4e18;
    static final int MOD = (int) 1e9 + 7;

    static int n, U, D, ans1, ans2;
    static ArrayList<Integer>[] g;
    static int[] par, dep;

    static void ask(ArrayList<Integer> toAsk) {
        out.print("? " + toAsk.size());
        for (int u : toAsk)
            out.print(" " + (u + 1));
        out.println();
        out.flush();
        U = in.nextInt() - 1;
        D = in.nextInt();
    }

    static void dfs(int u) {
        for (int v : g[u]) {
            if (par[v] == -1) {
                par[v] = u;
                dep[v] = dep[u] + 1;
                dfs(v);
            }
        }
    }

    static void solve() {
        n = in.nextInt();

        g = new ArrayList[n]; Arrays.setAll(g, i -> new ArrayList<>());
        for (int i = 0; i < n - 1; i++) {
            int u = in.nextInt() - 1;
            int v = in.nextInt() - 1;
            g[u].add(v);
            g[v].add(u);
        }

        ArrayList<Integer> all = new ArrayList<>();
        for (int u = 0; u < n; u++)
            all.add(u);

        ask(all);

        int root = U;
        int len = D;

        par = new int[n]; Arrays.fill(par, -1);
        dep = new int[n];
        par[root] = root;
        dep[root] = 0;
        dfs(root);

        ArrayList<Integer> lowLevel = new ArrayList<>();
        int maxDep = 0;
        for (int u = 0; u < n; u++)
            maxDep = Math.max(maxDep, dep[u]);
        int d = Math.min(len, maxDep);
        for (int u = 0; u < n; u++) {
            if (dep[u] == d)
                lowLevel.add(u);
        }

        ask(lowLevel);
        d = (D - len) / 2;
        ans1 = U;
        for (int i = 0; i < d; i++)
            ans1 = par[ans1];

        int not = ans1;
        while (dep[not] != len - dep[ans1])
            not = par[not];

        ArrayList<Integer> highLevel = new ArrayList<>();
        for (int u = 0; u < n; u++) {
            if (dep[u] == len - dep[ans1] && u != not)
                highLevel.add(u);
        }

        if (highLevel.size() == 0) {
            ans2 = root;
        } else {
            ask(highLevel);
            ans2 = U;
        }

        out.println("! " + (ans1 + 1) + " " + (ans2 + 1));
        out.flush();

    }

    public static void main(String[] args) throws FileNotFoundException {
        in = new FastReader(System.in);
//        in = new FastReader(new FileInputStream("sometext.txt"));
        out = new PrintWriter(System.out);
//        out = new PrintWriter(new FileOutputStream("output.txt"));

        int T = 1;
        T = in.nextInt();
        while (T-- > 0)
            solve();

//        Thread thread = new Thread(null, () -> {
//            solve();
//        }, "Main", 1 << 28);
//        thread.start();
//        try {
//            thread.join();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

//        out.flush();
        out.close();
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        FastReader(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        Integer nextInt() {
            return Integer.parseInt(next());
        }

        Long nextLong() {
            return Long.parseLong(next());
        }

        Double nextDouble() {
            return Double.parseDouble(next());
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(nextLine());
            }
            return st.nextToken();
        }

        String nextLine() {
            String s = "";
            try {
                s = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return s;
        }
    }

    static void dbg(Object... args) {
        for (Object arg : args)
            out.print(arg + " ");
        out.println();
    }

}


import java.io.*;
import java.util.*;

/*
polyakoff
*/

public class Main {

    static FastReader in;
    static PrintWriter out;
    static Random rand = new Random();
    static final int oo = (int) 2e9;
    static final long OO = (long) 4e18;
    static final int MOD = (int) 1e9 + 7;

    static int n, U, D, ans1, ans2;
    static ArrayList<Integer>[] g;
    static int[] par, dep;

    static void ask(ArrayList<Integer> toAsk) {
        out.print("? " + toAsk.size());
        for (int u : toAsk)
            out.print(" " + (u + 1));
        out.println();
        out.flush();
        U = in.nextInt() - 1;
        D = in.nextInt();
    }

    static void dfs(int u) {
        for (int v : g[u]) {
            if (par[v] == -1) {
                par[v] = u;
                dep[v] = dep[u] + 1;
                dfs(v);
            }
        }
    }

    static void solve() {
        n = in.nextInt();

        g = new ArrayList[n]; Arrays.setAll(g, i -> new ArrayList<>());
        for (int i = 0; i < n - 1; i++) {
            int u = in.nextInt() - 1;
            int v = in.nextInt() - 1;
            g[u].add(v);
            g[v].add(u);
        }

        ArrayList<Integer> all = new ArrayList<>();
        for (int u = 0; u < n; u++)
            all.add(u);

        ask(all);

        int root = U;
        int len = D;

        par = new int[n]; Arrays.fill(par, -1);
        dep = new int[n];
        par[root] = root;
        dep[root] = 0;
        dfs(root);

        ArrayList<Integer> lowLevel = new ArrayList<>();
        int maxDep = 0;
        for (int u = 0; u < n; u++)
            maxDep = Math.max(maxDep, dep[u]);
        int d = Math.min(len, maxDep);
        for (int u = 0; u < n; u++) {
            if (dep[u] == d)
                lowLevel.add(u);
        }

        ask(lowLevel);
        d = (D - len) / 2;
        ans1 = U;
        for (int i = 0; i < d; i++)
            ans1 = par[ans1];

        int not = ans1;
        while (dep[not] != len - dep[ans1])
            not = par[not];

        ArrayList<Integer> highLevel = new ArrayList<>();
        for (int u = 0; u < n; u++) {
            if (dep[u] == len - dep[ans1] && u != not)
                highLevel.add(u);
        }

        if (highLevel.size() == 0) {
            ans2 = root;
        } else {
            ask(highLevel);
            ans2 = U;
        }

        out.println("! " + (ans1 + 1) + " " + (ans2 + 1));
//        out.flush();
        in.next();

    }

    public static void main(String[] args) throws FileNotFoundException {
        in = new FastReader(System.in);
//        in = new FastReader(new FileInputStream("sometext.txt"));
        out = new PrintWriter(System.out);
//        out = new PrintWriter(new FileOutputStream("output.txt"));

        int T = 1;
        T = in.nextInt();
        while (T-- > 0)
            solve();

//        Thread thread = new Thread(null, () -> {
//            solve();
//        }, "Main", 1 << 28);
//        thread.start();
//        try {
//            thread.join();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

//        out.flush();
        out.close();
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        FastReader(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        Integer nextInt() {
            return Integer.parseInt(next());
        }

        Long nextLong() {
            return Long.parseLong(next());
        }

        Double nextDouble() {
            return Double.parseDouble(next());
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(nextLine());
            }
            return st.nextToken();
        }

        String nextLine() {
            String s = "";
            try {
                s = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return s;
        }
    }

    static void dbg(Object... args) {
        for (Object arg : args)
            out.print(arg + " ");
        out.println();
    }

}


import java.io.*;
import java.util.*;

/*
polyakoff
*/

public class Main {

    static FastReader in;
    static PrintWriter out;
    static Random rand = new Random();
    static final int oo = (int) 2e9;
    static final long OO = (long) 4e18;
    static final int MOD = (int) 1e9 + 7;

    static int n, U, D, ans1, ans2;
    static ArrayList<Integer>[] g;
    static int[] par, dep;

    static void ask(ArrayList<Integer> toAsk) {
        out.print("? " + toAsk.size());
        for (int u : toAsk)
            out.print(" " + (u + 1));
        out.println();
        out.flush();
        U = in.nextInt() - 1;
        D = in.nextInt();
    }

    static void dfs(int u) {
        for (int v : g[u]) {
            if (par[v] == -1) {
                par[v] = u;
                dep[v] = dep[u] + 1;
                dfs(v);
            }
        }
    }

    static void solve() {
        n = in.nextInt();

        g = new ArrayList[n]; Arrays.setAll(g, i -> new ArrayList<>());
        for (int i = 0; i < n - 1; i++) {
            int u = in.nextInt() - 1;
            int v = in.nextInt() - 1;
            g[u].add(v);
            g[v].add(u);
        }

        ArrayList<Integer> all = new ArrayList<>();
        for (int u = 0; u < n; u++)
            all.add(u);

        ask(all);

        int root = U;
        int len = D;

        par = new int[n]; Arrays.fill(par, -1);
        dep = new int[n];
        par[root] = root;
        dep[root] = 0;
        dfs(root);

        ArrayList<Integer> lowLevel = new ArrayList<>();
        int maxDep = 0;
        for (int u = 0; u < n; u++)
            maxDep = Math.max(maxDep, dep[u]);
        int d = Math.min(len, maxDep);
        for (int u = 0; u < n; u++) {
            if (dep[u] == d)
                lowLevel.add(u);
        }

        ask(lowLevel);
        d = (D - len) / 2;
        ans1 = U;
        for (int i = 0; i < d; i++)
            ans1 = par[ans1];

        int not = ans1;
        while (dep[not] != len - dep[ans1])
            not = par[not];

        ArrayList<Integer> highLevel = new ArrayList<>();
        for (int u = 0; u < n; u++) {
            if (dep[u] == len - dep[ans1] && u != not)
                highLevel.add(u);
        }

        if (highLevel.size() == 0) {
            ans2 = root;
        } else {
            ask(highLevel);
            ans2 = U;
        }

        out.println("! " + (ans1 + 1) + " " + (ans2 + 1));
        out.flush();

        in.next();

    }

    public static void main(String[] args) throws FileNotFoundException {
        in = new FastReader(System.in);
//        in = new FastReader(new FileInputStream("sometext.txt"));
        out = new PrintWriter(System.out);
//        out = new PrintWriter(new FileOutputStream("output.txt"));

        int T = 1;
        T = in.nextInt();
        while (T-- > 0)
            solve();

//        Thread thread = new Thread(null, () -> {
//            solve();
//        }, "Main", 1 << 28);
//        thread.start();
//        try {
//            thread.join();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

//        out.flush();
        out.close();
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        FastReader(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        Integer nextInt() {
            return Integer.parseInt(next());
        }

        Long nextLong() {
            return Long.parseLong(next());
        }

        Double nextDouble() {
            return Double.parseDouble(next());
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(nextLine());
            }
            return st.nextToken();
        }

        String nextLine() {
            String s = "";
            try {
                s = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return s;
        }
    }

    static void dbg(Object... args) {
        for (Object arg : args)
            out.print(arg + " ");
        out.println();
    }

}


import java.io.*;
import java.util.*;

/*
polyakoff
*/

public class Main {

    static FastReader in;
    static PrintWriter out;
    static Random rand = new Random();
    static final int oo = (int) 2e9;
    static final long OO = (long) 4e18;
    static final int MOD = (int) 1e9 + 7;

    static int n, U, D, ans1, ans2;
    static ArrayList<Integer>[] g;
    static int[] par, dep;

    static void ask(ArrayList<Integer> toAsk) {
        out.print("? " + toAsk.size());
        for (int u : toAsk)
            out.print(" " + (u + 1));
        out.println();
        out.flush();
        U = in.nextInt() - 1;
        D = in.nextInt();
    }

    static void dfs(int u) {
        for (int v : g[u]) {
            if (par[v] == -1) {
                par[v] = u;
                dep[v] = dep[u] + 1;
                dfs(v);
            }
        }
    }

    static void solve() {
        n = in.nextInt();

        g = new ArrayList[n]; Arrays.setAll(g, i -> new ArrayList<>());
        for (int i = 0; i < n - 1; i++) {
            int u = in.nextInt() - 1;
            int v = in.nextInt() - 1;
            g[u].add(v);
            g[v].add(u);
        }

        ArrayList<Integer> all = new ArrayList<>();
        for (int u = 0; u < n; u++)
            all.add(u);

        ask(all);

        int root = U;
        int len = D;

        par = new int[n]; Arrays.fill(par, -1);
        dep = new int[n];
        par[root] = root;
        dep[root] = 0;
        dfs(root);

        ArrayList<Integer> lowLevel = new ArrayList<>();
        int maxDep = 0;
        for (int u = 0; u < n; u++)
            maxDep = Math.max(maxDep, dep[u]);
        int d = Math.min(len, maxDep);
        for (int u = 0; u < n; u++) {
            if (dep[u] == d)
                lowLevel.add(u);
        }

        ask(lowLevel);
        d = (D - len) / 2;
        ans1 = U;
        for (int i = 0; i < d; i++)
            ans1 = par[ans1];

        int not = ans1;
        while (dep[not] != len - dep[ans1])
            not = par[not];

        ArrayList<Integer> highLevel = new ArrayList<>();
        for (int u = 0; u < n; u++) {
            if (dep[u] == len - dep[ans1] && u != not)
                highLevel.add(u);
        }

        if (highLevel.size() == 0) {
            ans2 = root;
        } else {
            ask(highLevel);
            ans2 = U;
        }

        out.println("! " + (ans1 + 1) + " " + (ans2 + 1));
        out.flush();
        if (!in.next().equals("Correct")) {
            out.flush();
            System.exit(0);
        }

    }

    public static void main(String[] args) throws FileNotFoundException {
        in = new FastReader(System.in);
//        in = new FastReader(new FileInputStream("sometext.txt"));
        out = new PrintWriter(System.out);
//        out = new PrintWriter(new FileOutputStream("output.txt"));

        int T = 1;
        T = in.nextInt();
        while (T-- > 0)
            solve();

//        Thread thread = new Thread(null, () -> {
//            solve();
//        }, "Main", 1 << 28);
//        thread.start();
//        try {
//            thread.join();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

//        out.flush();
        out.close();
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        FastReader(InputStream is) {
            br = new BufferedReader(new InputStreamReader(is));
        }

        Integer nextInt() {
            return Integer.parseInt(next());
        }

        Long nextLong() {
            return Long.parseLong(next());
        }

        Double nextDouble() {
            return Double.parseDouble(next());
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(nextLine());
            }
            return st.nextToken();
        }

        String nextLine() {
            String s = "";
            try {
                s = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return s;
        }
    }

    static void dbg(Object... args) {
        for (Object arg : args)
            out.print(arg + " ");
        out.println();
    }

}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.util.Collection;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TheHiddenPair solver = new TheHiddenPair();
        solver.solve(1, in, out);
        out.close();
    }

    static class TheHiddenPair {
        ArrayList<Integer>[] depths;
        int[] par = new int[1000];

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int T = in.nextInt();
            tests:
            while (T-- > 0) {
                int N = in.nextInt();
                depths = new ArrayList[N];
                ArrayList<Integer>[] tree = new ArrayList[N];
                ArrayList<Integer> all = new ArrayList<>();
                for (int i = 0; i < N; i++) {
                    depths[i] = new ArrayList<>();
                    tree[i] = new ArrayList<>();
                    all.add(i);
                }
                for (int i = 0; i < N - 1; i++) {
                    int a = in.nextInt() - 1;
                    int b = in.nextInt() - 1;
                    tree[a].add(b);
                    tree[b].add(a);
                }
                int[] root = query(all, in, out);
                if (root[0] == -1) {
                    return;
                }
                root(root[0], root[0], 0, tree);
                iter:
                for (int i = N - 1; i >= 0; i--) {
                    if (depths[i].size() > 0) {
                        int[] last = new int[2];
                        int low = 0;
                        int high = i;
                        while (low < high) {
                            int mid = (low + high + 1) / 2;
                            int[] q = query(depths[mid], in, out);
                            if (q[1] == -1) {
                                return;
                            }
                            if (q[1] == root[1]) {
                                low = mid;
                                last = q;
                            } else {
                                high = mid - 1;
                            }
                        }
                        int u = last[0];
                        int d = low;
                        while (par[u] != u) {
                            depths[d].remove((Object) u);
                            u = par[u];
                            d--;
                        }
                        int left = root[1] - low;
                        int[] other = new int[]{root[0], 1};
                        if (left != 0) {
                            other = query(depths[left], in, out);
                        }
                        out.println("! " + (other[0] + 1) + " " + (last[0] + 1));
                        out.flush();
                        String res = in.next();
                        if (res.equals("Correct")) {
                            continue tests;
                        } else {
                            return;
                        }
                    }
                }
            }
        }

        void root(int n, int p, int d, ArrayList<Integer>[] tree) {
            par[n] = p;
            depths[d].add(n);
            for (int e : tree[n]) {
                if (e != p) {
                    root(e, n, d + 1, tree);
                }
            }
        }

        int[] query(Collection<Integer> col, InputReader in, PrintWriter out) {
            out.println("? " + col.size());
            for (int i : col) {
                out.println(i + 1);
            }
            out.flush();
            int x = in.nextInt();
            int d = in.nextInt();
            return new int[]{x - 1, d};
        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

    }
}


#include<bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#define For(i, a, b) for(register int i = (a), en = (b); i <= en; ++i)
#define Rof(i, a, b) for(int i = (a), en = (b); i >= en; --i)
#define Tra(u, i) for(int i = hd[u]; ~i; i = e[i].net)
#define LL long long
#define DD double
#define LD long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define inf 0x3f3f3f3f
#define eps 1e-12
#define maxn 100000
using namespace std;

int n, m, k, b[2 * maxn + 5], tot = 0, cnt = 0, f[2][256], to[4 * maxn + 5][13], ito[4 * maxn + 5][13], as = 0, bit[256];
pair<int, int> op[maxn + 5], op1[4 * maxn + 5];
vector<int> vec[4 * maxn + 5];

void chkmx(int &x, int y){if(x < y) x = y;}

int main(){
	//freopen("in", "r", stdin);
	memset(to, -1, sizeof to);
	For(i, 0, 255) bit[i] = bit[i >> 1] + (i & 1);
	scanf("%d %d %d", &n, &m, &k);
	For(i, 1, n){
		scanf("%d %d", &op[i].fir, &op[i].sec);
		b[++tot] = op[i].fir;
		b[++tot] = op[i].sec;
	}
	sort(b + 1, b + tot + 1);
	tot = unique(b + 1, b + tot + 1) - b - 1;
	For(i, 1, tot){
		op1[++cnt] = mp(b[i], b[i]);
		if(i != tot && b[i + 1] - b[i] >= 2) op1[++cnt] = mp(b[i] + 1, b[i + 1] - 1);
	}
	For(i, 1, n){
		int l = op[i].fir, r = op[i].sec;
		op[i].fir = lower_bound(op1 + 1, op1 + cnt + 1, mp(l, 0)) - op1;
		op[i].sec = lower_bound(op1 + 1, op1 + cnt + 1, mp(r, 0)) - op1;
		For(j, op[i].fir, op[i].sec) vec[j].pb(i);
	}
	For(i, 1, cnt) For(j, 0, vec[i].size() - 1) For(p, 0, vec[i + 1].size() - 1)
		if(vec[i][j] == vec[i + 1][p]){to[i][j] = p; ito[i + 1][p] = 1; break;}
	int now = 0;
	For(i, 1, cnt){
		memset(f[now], 0, sizeof f[now]);
		now = !now;
		For(j, 0, vec[i].size() - 1){
			if(ito[i][j]) continue;
			For(p, 0, 255) if((p >> j) & 1) chkmx(f[now][p], f[now][p ^ (1 << j)]);
		}
		For(j, 0, 255) f[now][j] += bit[j] & 1 ? op1[i].sec - op1[i].fir + 1 : 0, chkmx(as, f[now][j]);
		if(i == cnt) continue;
		For(j, 0, 255){
			int sta = 0;
			For(p, 0, vec[i].size() - 1) if(((j >> p) & 1) && to[i][p] != -1) sta |= 1 << to[i][p];
			chkmx(f[!now][sta], f[now][j]);
		}
	}
	printf("%d\n", as);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define mp(a, b) make_pair(a, b)
typedef pair<int, int> pii;
const int maxn = 2e5 + 10;
const int maxs = 1 << 8;
const int inf = 1e9 + 10;
vector<pii> event;
set<int> bit;
int n, m, k, s;
int pos[maxn], dp[maxn][maxs];
inline int fact(int x) { return __builtin_popcount(x) & 1;}
int main()
{
	scanf("%d%d%d", &n, &m, &k);
	s = 1 << k;
	for(int i = 1; i <= n; ++i)
	{
		int l, r;
		scanf("%d%d", &l, &r);
		event.emplace_back(l, i);
		event.emplace_back(r + 1, -i);
	}
	for(int i = 0; i < k; ++i)
		bit.insert(i);
	sort(event.begin(), event.end());
	for(int i = 1; i <= event.size(); ++i)
	{
		pii v = event[i - 1];
		int id = v.second, len = ((i == event.size()) ? 0 : event[i].first - v.first);
		if(id > 0) //insert
		{
			pos[id] = *bit.begin();
			bit.erase(bit.begin());
			for(int j = 0; j < s; ++j)
				if(j & (1 << pos[id]))
					dp[i][j] = dp[i - 1][j ^ (1 << pos[id])] + fact(j) * len;
				else
					dp[i][j] = dp[i - 1][j] + fact(j) * len;
		}
		else //erase
		{
			id = -id;
			bit.insert(pos[id]);
			for(int j = 0; j < s; ++j)
				if(!(j & (1 << pos[id])))
					dp[i][j] = max(dp[i - 1][j], dp[i - 1][j ^ (1 << pos[id])]) + fact(j) * len;
				else
					dp[i][j] = dp[i - 1][j] + fact(j) * len;
		}
	}
	printf("%d\n", dp[event.size()][0]);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define mp(a, b) make_pair(a, b)
typedef pair<int, int> pii;
const int maxn = 1e5 + 10;
const int maxs = 1 << 8;
const int inf = 1e9 + 10;
vector<pii> event;
set<int> bit;
int n, m, k, s;
int pos[maxn], dp[maxn][maxs];
inline int fact(int x) { return __builtin_popcount(x) & 1;}
int main()
{
	scanf("%d%d%d", &n, &m, &k);
	s = 1 << k;
	for(int i = 1; i <= n; ++i)
	{
		int l, r;
		scanf("%d%d", &l, &r);
		event.emplace_back(l, i);
		event.emplace_back(r + 1, -i);
	}
	for(int i = 0; i < k; ++i)
		bit.insert(i);
	sort(event.begin(), event.end());
	for(int i = 1; i <= event.size(); ++i)
	{
		pii v = event[i - 1];
		int id = v.second, len = ((i == event.size()) ? 0 : event[i].first - v.first);
		if(id > 0) //insert
		{
			pos[id] = *bit.begin();
			bit.erase(bit.begin());
			for(int j = 0; j < s; ++j)
				if(j & (1 << pos[id]))
					dp[i][j] = dp[i - 1][j ^ (1 << pos[id])] + fact(j) * len;
				else
					dp[i][j] = dp[i - 1][j] + fact(j) * len;
		}
		else //erase
		{
			id = -id;
			bit.insert(pos[id]);
			for(int j = 0; j < s; ++j)
				if(!(j & (1 << pos[id])))
					dp[i][j] = max(dp[i - 1][j], dp[i - 1][j ^ (1 << pos[id])]) + fact(j) * len;
				else
					dp[i][j] = dp[i - 1][j] + fact(j) * len;
		}
	}
	printf("%d\n", dp[event.size()][0]);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define mp(a, b) make_pair(a, b)
typedef pair<int, int> pii;
const int maxn = 1e5 + 10;
const int maxs = 1 << 8;
const int inf = 1e9 + 10;
vector<pii> event;
set<int> bit;
int n, m, k, s;
int pos[8], dp[maxn][maxs];
inline int fact(int x) { return __builtin_popcount(x) & 1;}
int main()
{
	scanf("%d%d%d", &n, &m, &k);
	s = 1 << k;
	for(int i = 1; i <= n; ++i)
	{
		int l, r;
		scanf("%d%d", &l, &r);
		event.emplace_back(l, i);
		event.emplace_back(r + 1, -i);
	}
	for(int i = 0; i < k; ++i)
		bit.insert(i);
	sort(event.begin(), event.end());
	for(int i = 1; i <= event.size(); ++i)
	{
		pii v = event[i - 1];
		int id = v.second, len = ((i == event.size()) ? 0 : event[i].first - v.first);
		if(id > 0) //insert
		{
			pos[id] = *bit.begin();
			bit.erase(bit.begin());
			for(int j = 0; j < s; ++j)
				if(j & (1 << pos[id]))
					dp[i][j] = dp[i - 1][j ^ (1 << pos[id])] + fact(j) * len;
				else
					dp[i][j] = dp[i - 1][j] + fact(j) * len;
		}
		else //erase
		{
			id = -id;
			bit.insert(pos[id]);
			for(int j = 0; j < s; ++j)
				if(!(j & (1 << pos[id])))
					dp[i][j] = max(dp[i - 1][j], dp[i - 1][j ^ (1 << pos[id])]) + fact(j) * len;
				else
					dp[i][j] = dp[i - 1][j] + fact(j) * len;
		}
	}
	printf("%d\n", dp[event.size()][0]);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define mp(a, b) make_pair(a, b)
typedef pair<int, int> pii;
const int maxn = 2e5 + 10;
const int maxs = 1 << 8;
const int inf = 1e9 + 10;
vector<pii> event;
set<int> bit;
int n, m, k, s;
int pos[maxn], dp[maxn][maxs];
inline int fact(int x) { return __builtin_popcount(x) & 1;}
int main()
{
	scanf("%d%d%d", &n, &m, &k);
	s = 1 << k;
	for(int i = 1; i <= n; ++i)
	{
		int l, r;
		scanf("%d%d", &l, &r);
		event.emplace_back(l, i);
		event.emplace_back(r + 1, -i);
	}
	for(int i = 0; i < k; ++i)
		bit.insert(i);
	sort(event.begin(), event.end());
	for(int i = 1; i <= event.size(); ++i)
	{
		pii v = event[i - 1];
		int id = v.second, len = ((i == event.size()) ? 0 : event[i].first - v.first);
		if(id > 0) //insert
		{
			pos[id] = *bit.begin();
			bit.erase(bit.begin());
			for(int j = 0; j < s; ++j)
				if(j & (1 << pos[id]))
					dp[i][j] = dp[i - 1][j ^ (1 << pos[id])] + fact(j) * len;
				else
					dp[i][j] = dp[i - 1][j] + fact(j) * len;
		}
		else //erase
		{
			id = -id;
			bit.insert(pos[id]);
			for(int j = 0; j < s; ++j)
				if(!(j & (1 << pos[id])))
					dp[i][j] = max(dp[i - 1][j], dp[i - 1][j ^ (1 << pos[id])]) + fact(j) * len;
				else
					dp[i][j] = -inf;
		}
	}
	printf("%d\n", dp[event.size()][0]);
	return 0;
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <functional>
#include <iostream>
#include <queue>
#include <cassert>

using namespace std;
typedef long long int64;

int main()
{
	ios::sync_with_stdio(0), cin.tie(0);

	int allMagic = 0, m = 0, limit = 0, newMagic = 0;
	cin >> allMagic >> m >> limit;
	vector <int> magicL(allMagic + 1, 0);
	vector <int> magicR(allMagic + 1, 0);
	vector <int> number;
	vector <int64> dp(1 << limit | 1);
	vector <int64> maxValue(1 << limit | 1);
	vector <int64> numberSize;
	vector <int> magicCovered(allMagic * 5 + 1);
	vector <int> magicEnd(allMagic * 5 + 1);
	vector <vector <bool>> isMagicCovered(allMagic * 5 + 1);
	vector <vector <bool>> isMagicEnd(allMagic * 5 + 1);
	vector <bool> isUseed(allMagic + 1);

	function <void()> init = [&]()
	{
		number.push_back(0);
		for (int i = 1; i <= allMagic; ++i)
		{
			cin >> magicL[i] >> magicR[i];
			number.push_back(magicL[i]);
			number.push_back(magicR[i]);
			number.push_back(max(magicL[i] - 1, 1));
		}
		sort(number.begin() + 1, number.end());
		newMagic = unique(number.begin() + 1, number.end()) - number.begin() - 1;
//		for (int g : number)
//			cout << g << '\n';
		for (int i = 1; i <= allMagic; ++i)
		{
			magicL[i] = lower_bound(number.begin() + 1, number.begin() + newMagic, magicL[i]) - number.begin() ;
			magicR[i] = lower_bound(number.begin() + 1, number.begin() + newMagic, magicR[i]) - number.begin() ;
//			cout << magicL[i] << " " << magicR[i] << '\n';
		}

		numberSize.resize(number.size() + 3);
		for (int i = 1;i <= newMagic; ++i)
		{
			numberSize[i] = number[i] - number[i - 1];
			assert(numberSize[i] > 0);
//			cout <<
			//cout << numberSize[i] << '\n';
		}
	};

	function <int(int)> count = [&](int s)
	{
		int res = 0;
		while (s > 0)
			res ^= 1, s -= s & -s;
		return res;
	};

	function <void()> solve = [&]()
	{
		for (int i = 1;i <= newMagic; ++i)
			isMagicCovered[i].resize(limit + 1),
			isMagicEnd[i].resize(limit + 1);

		for (int i = 1; i <= limit; ++i)
		{
			int lowest = 0;
			for (int j = 1; j <= allMagic; ++j)
			{
				if (isUseed[j] || lowest >= magicL[j])
					continue;
				isUseed[j] = 1;

				for (int k = magicL[j]; k <= magicR[j]; ++k)
					isMagicCovered[k][i] = 1;

				isMagicEnd[magicR[j]][i] = 1;
				lowest = magicR[j];
			}
		}

		for (int i = 1; i <= newMagic; ++i)
		{
			for (int j = 1;j <= limit; ++j)
				magicCovered[i] |= (1 << j - 1) * int(isMagicCovered[i][j]),
				magicEnd[i] |= (1 << j - 1) * int(isMagicEnd[i][j]);
//			cout << magicCovered[i] << " " << magicEnd[i] << '\n';
		}

		int allBitMakes = 1 << limit;
		vector <int> f(allBitMakes + 1, 0);
		for (int i = 1; i < allBitMakes; ++i)
			f[i] = count(i);
		//	cout << f[i] << '\n';

		for (int i = 1; i <= newMagic; ++i)
		{
			for (int s = 0; s < allBitMakes; ++s)
			{
				if ((s | magicCovered[i]) != magicCovered[i])
					continue;
				int basic = (s & magicCovered[i - 1]) & (magicCovered[i - 1] ^ magicEnd[i - 1]);
				for (int k = magicEnd[i - 1]; k; k = (k - 1) & magicEnd[i - 1])
					dp[s] = max(dp[s], maxValue[basic | k] + f[s] * numberSize[i]);

				dp[s] = max(dp[s], maxValue[basic] + f[s] * numberSize[i]);
//				cout << dp[s] << " " << numberSize[i] << '\n';
			}

			for (int s = 0;s < allBitMakes; ++s)
				maxValue[s] = dp[s],
				dp[s] = 0;
		}

//		cout << number.size() << '\n';

		cout << *max_element(maxValue.begin(), maxValue.end()) << '\n';
	};

	init();
	solve();

	return 0;
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <functional>
#include <iostream>
#include <queue>
#include <cassert>

using namespace std;
typedef long long int64;

int main()
{
	ios::sync_with_stdio(0), cin.tie(0);

	int allMagic = 0, m = 0, limit = 0, newMagic = 0;
	cin >> allMagic >> m >> limit;
	vector <int> magicL(allMagic + 1, 0);
	vector <int> magicR(allMagic + 1, 0);
	vector <int> number;
	vector <int64> dp(1 << limit | 1);
	vector <int64> maxValue(1 << limit | 1);
	vector <int64> numberSize;
	vector <int> magicCovered(allMagic * 5 + 1);
	vector <int> magicEnd(allMagic * 5 + 1);
	vector <vector <bool>> isMagicCovered(allMagic * 5 + 1);
	vector <vector <bool>> isMagicEnd(allMagic * 5 + 1);
	vector <bool> isUseed(allMagic + 1);

	function <void()> init = [&]()
	{
		number.push_back(0);
		for (int i = 1; i <= allMagic; ++i)
		{
			cin >> magicL[i] >> magicR[i];
			number.push_back(magicL[i]);
			number.push_back(magicR[i]);
			number.push_back(max(magicL[i] - 1, 1));
		}
		sort(number.begin() + 1, number.end());
		newMagic = unique(number.begin() + 1, number.end()) - number.begin() - 1;
//		for (int g : number)
//			cout << g << '\n';
		for (int i = 1; i <= allMagic; ++i)
		{
			magicL[i] = lower_bound(number.begin() + 1, number.begin() + newMagic, magicL[i]) - number.begin() ;
			magicR[i] = lower_bound(number.begin() + 1, number.begin() + newMagic, magicR[i]) - number.begin() ;
//			cout << magicL[i] << " " << magicR[i] << '\n';
		}

		numberSize.resize(number.size() + 3);
		for (int i = 1;i <= newMagic; ++i)
		{
			numberSize[i] = number[i] - number[i - 1];
//			cout <<
			//cout << numberSize[i] << '\n';
		}
	};

	function <int(int)> count = [&](int s)
	{
		int res = 0;
		while (s > 0)
			res ^= 1, s -= s & -s;
		return res;
	};

	function <void()> solve = [&]()
	{
		for (int i = 1;i <= newMagic; ++i)
			isMagicCovered[i].resize(limit + 1),
			isMagicEnd[i].resize(limit + 1);

		for (int i = 1; i <= limit; ++i)
		{
			int lowest = 0;
			for (int j = 1; j <= allMagic; ++j)
			{
				if (isUseed[j] || lowest >= magicL[j])
					continue;
				isUseed[j] = 1;

				for (int k = magicL[j]; k <= magicR[j]; ++k)
					isMagicCovered[k][i] = 1;

				isMagicEnd[magicR[j]][i] = 1;
				lowest = magicR[j];
			}
		}

		for (int i = 1; i <= newMagic; ++i)
		{
			for (int j = 1;j <= limit; ++j)
				magicCovered[i] |= (1 << j - 1) * int(isMagicCovered[i][j]),
				magicEnd[i] |= (1 << j - 1) * int(isMagicEnd[i][j]);
//			cout << magicCovered[i] << " " << magicEnd[i] << '\n';
		}

		int allBitMakes = 1 << limit;
		vector <int> f(allBitMakes + 1, 0);
		for (int i = 1; i < allBitMakes; ++i)
			f[i] = count(i);
		//	cout << f[i] << '\n';

		for (int i = 1; i <= newMagic; ++i)
		{
			for (int s = 0; s < allBitMakes; ++s)
			{
				if ((s | magicCovered[i]) != magicCovered[i])
					continue;
				int basic = (s & magicCovered[i - 1]) & (magicCovered[i - 1] ^ magicEnd[i - 1]);
				for (int k = magicEnd[i - 1]; k; k = (k - 1) & magicEnd[i - 1])
					dp[s] = max(dp[s], maxValue[basic | k] + f[s] * numberSize[i]);

				dp[s] = max(dp[s], maxValue[basic] + f[s] * numberSize[i]);
//				cout << dp[s] << " " << numberSize[i] << '\n';
			}

			for (int s = 0;s < allBitMakes; ++s)
				maxValue[s] = dp[s],
				dp[s] = 0;
		}

//		cout << number.size() << '\n';

		cout << *max_element(maxValue.begin(), maxValue.end()) << '\n';
	};

	init();
	solve();

	return 0;
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <functional>
#include <iostream>
#include <queue>
#include <cassert>

using namespace std;
typedef long long int64;

int main()
{
	ios::sync_with_stdio(0), cin.tie(0);

	int allMagic = 0, m = 0, limit = 0, newMagic = 0;
	cin >> allMagic >> m >> limit;
	vector <int> magicL(allMagic + 1, 0);
	vector <int> magicR(allMagic + 1, 0);
	vector <int> number;
	vector <int> dp(1 << limit | 1);
	vector <int> maxValue(1 << limit | 1);
	vector <int> numberSize;
	vector <int> magicCovered(allMagic * 5 + 1);
	vector <int> magicEnd(allMagic * 5 + 1);
	vector <vector <bool>> isMagicCovered(allMagic * 5 + 1);
	vector <vector <bool>> isMagicEnd(allMagic * 5 + 1);
	vector <bool> isUseed(allMagic + 1);

	function <void()> init = [&]()
	{
		for (int i = 1; i <= allMagic; ++i)
		{
			cin >> magicL[i] >> magicR[i];
			number.push_back(magicL[i]);
			number.push_back(magicR[i]);
			number.push_back(max(magicL[i] - 1, 1));
		}

		sort(number.begin(), number.end());
		newMagic = unique(number.begin(), number.end()) - number.begin();
//		for (int g : number)
//			cout << g << '\n';
		for (int i = 1; i <= allMagic; ++i)
		{
			magicL[i] = lower_bound(number.begin(), number.begin() + newMagic, magicL[i]) - number.begin() + 1;
			magicR[i] = lower_bound(number.begin(), number.begin() + newMagic, magicR[i]) - number.begin() + 1;
//			cout << magicL[i] << " " << magicR[i] << '\n';
		}

		numberSize.resize(number.size() + 3);
		for (int i = 1;i < newMagic; ++i)
		{
			numberSize[i] = number[i] - number[i - 1];
//			cout <<
			//cout << numberSize[i] << '\n';
		} numberSize[newMagic] = 1;
	};

	function <int(int)> count = [&](int s)
	{
		int res = 0;
		while (s > 0)
			res ^= 1, s -= s & -s;
		return res;
	};

	function <void()> solve = [&]()
	{
		for (int i = 1;i <= newMagic; ++i)
			isMagicCovered[i].resize(limit + 1),
			isMagicEnd[i].resize(limit + 1);

		for (int i = 1; i <= limit; ++i)
		{
			int lowest = 0;
			for (int j = 1; j <= allMagic; ++j)
			{
				if (isUseed[j] || lowest >= magicL[j])
					continue;
				isUseed[j] = 1;

				for (int k = magicL[j]; k <= magicR[j]; ++k)
					isMagicCovered[k][i] = 1;

				isMagicEnd[magicR[j]][i] = 1;
				lowest = magicR[j];
			}
		}

		for (int i = 1; i <= newMagic; ++i)
		{
			for (int j = 1;j <= limit; ++j)
				magicCovered[i] |= (1 << j - 1) * int(isMagicCovered[i][j]),
				magicEnd[i] |= (1 << j - 1) * int(isMagicEnd[i][j]);
//			cout << magicCovered[i] << " " << magicEnd[i] << '\n';
		}

		int allBitMakes = 1 << limit;
		vector <int> f(allBitMakes + 1, 0);
		for (int i = 1; i < allBitMakes; ++i)
			f[i] = count(i);
		//	cout << f[i] << '\n';

		for (int i = 1; i <= newMagic; ++i)
		{
			for (int s = 0; s < allBitMakes; ++s)
			{
				if ((s | magicCovered[i]) != magicCovered[i])
					continue;
				int basic = (s & magicCovered[i - 1]) & (magicCovered[i - 1] ^ magicEnd[i - 1]);
				for (int k = magicEnd[i - 1]; k; k = (k - 1) & magicEnd[i - 1])
				{
					dp[s] = max(dp[s], maxValue[basic | k] + f[s] * numberSize[i]);
				}

				dp[s] = max(dp[s], maxValue[basic] + f[s] * numberSize[i]);
//				cout << dp[s] << " " << numberSize[i] << '\n';
			}

			for (int s = 0;s < allBitMakes; ++s)
				maxValue[s] = dp[s],
				dp[s] = 0;
		}

//		cout << number.size() << '\n';

		cout << *max_element(maxValue.begin(), maxValue.end()) << '\n';
	};

	init();
	solve();

	return 0;
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <functional>
#include <iostream>
#include <queue>
#include <cassert>

using namespace std;
typedef long long int64;

int main()
{
	ios::sync_with_stdio(0), cin.tie(0);

	int allMagic = 0, m = 0, limit = 0, newMagic = 0;
	cin >> allMagic >> m >> limit;
	struct Magic
	{
		int l, r;
		bool operator < (const Magic& a) const
		{
			if (l != a.l)
				return l < a.l;
			return r < a.r;
		}
	} magic[allMagic + 1];

	vector <int> number;
	vector <int64> dp(1 << limit | 1);
	vector <int64> maxValue(1 << limit | 1);
	vector <int64> numberSize(allMagic);
	vector <int> magicCovered(allMagic * 5 + 1);
	vector <int> magicEnd(allMagic * 5 + 1);
	vector <vector <bool>> isMagicCovered(allMagic * 5 + 1);
	vector <vector <bool>> isMagicEnd(allMagic * 5 + 1);
	vector <bool> isUseed(allMagic + 1);

	function <void()> init = [&]()
	{
		number.push_back(0);
		for (int i = 1; i <= allMagic; ++i)
		{
			cin >> magic[i].l >> magic[i].r;
			number.push_back(magic[i].l);
			number.push_back(magic[i].r);
			number.push_back(max(magic[i].l - 1, 1));
		}
		sort(number.begin(), number.end());
		newMagic = unique(number.begin() + 1, number.end()) - number.begin() - 1;
//		cerr << newMagic << '\n';
//		cout << number[newMagic] << '\n';
//		for (int g : number)
//			cout << g << '\n';
		numberSize.resize(number.size() + 3);
		for (int i = 1; i <= allMagic; ++i)
		{
			magic[i].l = lower_bound(number.begin() + 1, number.begin() + newMagic, magic[i].l) - number.begin() ;
			magic[i].r = lower_bound(number.begin() + 1, number.begin() + newMagic, magic[i].r) - number.begin() ;
//			cerr << magic.magicL[i] << " " << magic[i].r[i] << '\n';
		}
		sort(magic + 1, magic + 1 + allMagic);
		for (int i = 1;i <= newMagic; ++i)
		{
			numberSize[i] = number[i] - number[i - 1];
			assert(numberSize[i] > 0);
//			cout <<
//			cout << numberSize[i] << '\n';
		}
	};

	function <int(int)> count = [&](int s)
	{
		int res = 0;
		while (s > 0)
			res ^= 1, s -= s & -s;
		return res;
	};

	function <void()> solve = [&]()
	{
		for (int i = 1;i <= newMagic; ++i)
			isMagicCovered[i].resize(limit + 1),
			isMagicEnd[i].resize(limit + 1);

		for (int i = 1; i <= limit; ++i)
		{
			int lowest = 0;
			for (int j = 1; j <= allMagic; ++j)
			{
				if (isUseed[j] || lowest >= magic[j].l)
					continue;
				isUseed[j] = 1;
//				cout << j << '\n';
				for (int k = magic[j].l; k <= magic[j].r; ++k)
					isMagicCovered[k][i] = 1;

				isMagicEnd[magic[j].r][i] = 1;
				lowest = magic[j].r;
			}
		}

		for (int i = 1; i <= newMagic; ++i)
		{
			for (int j = 1;j <= limit; ++j)
				magicCovered[i] |= (1 << j - 1) * int(isMagicCovered[i][j]),
				magicEnd[i] |= (1 << j - 1) * int(isMagicEnd[i][j]);
//			cout << magicCovered[i] << " " << magicEnd[i] << '\n';
		}

		int allBitMakes = 1 << limit;
		vector <int> f(allBitMakes + 1, 0);
		for (int i = 1; i < allBitMakes; ++i)
			f[i] = count(i);
		//	cout << f[i] << '\n';

		for (int i = 1; i <= newMagic; ++i)
		{
			for (int s = 0; s < allBitMakes; ++s)
			{
				if ((s | magicCovered[i]) != magicCovered[i])
					continue;
				int basic = (s & magicCovered[i - 1]) & (magicCovered[i - 1] ^ magicEnd[i - 1]);
				for (int k = magicEnd[i - 1]; k; k = (k - 1) & magicEnd[i - 1])
					dp[s] = max(dp[s], maxValue[basic | k] + f[s] * numberSize[i]);

				dp[s] = max(dp[s], maxValue[basic] + f[s] * numberSize[i]);
//				cout << dp[s] << " " << numberSize[i] << '\n';
			}

			for (int s = 0;s < allBitMakes; ++s)
				maxValue[s] = dp[s],
				dp[s] = 0;
		}

//		cout << number.size() << '\n';

		cout << *max_element(maxValue.begin(), maxValue.end()) << '\n';
	};

	init();
	solve();

	return 0;
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <functional>
#include <iostream>
#include <queue>
#include <cassert>

using namespace std;
typedef long long int64;

int main()
{
	ios::sync_with_stdio(0), cin.tie(0);

	int allMagic = 0, m = 0, limit = 0, newMagic = 0;
	cin >> allMagic >> m >> limit;
	struct Magic
	{
		int l, r;
		bool operator < (const Magic& a) const
		{
			if (l != a.l)
				return l < a.l;
			return r < a.r;
		}
	} magic[allMagic + 1];

	vector <int> number;
	vector <int> dp(1 << limit | 1);
	vector <int> maxValue(1 << limit | 1);
	vector <int> numberSize(allMagic + 1);
	vector <int> magicCovered(allMagic * 5 + 1);
	vector <int> magicEnd(allMagic * 5 + 1);
	vector <vector <bool>> isMagicCovered(allMagic * 5 + 1);
	vector <vector <bool>> isMagicEnd(allMagic * 5 + 1);
	vector <bool> isUseed(allMagic + 1);

	function <void()> init = [&]()
	{
		number.push_back(0);
		for (int i = 1; i <= allMagic; ++i)
		{
			cin >> magic[i].l >> magic[i].r;
			number.push_back(magic[i].l);
			number.push_back(magic[i].r);
			number.push_back(max(magic[i].l - 1, 1));
		}
		sort(number.begin(), number.end());
		newMagic = unique(number.begin() + 1, number.end()) - number.begin() - 1;
//		cerr << newMagic << '\n';
//		cout << number[newMagic] << '\n';
//		for (int g : number)
//			cout << g << '\n';
		numberSize.resize(number.size() + 3);
		for (int i = 1; i <= allMagic; ++i)
		{
			magic[i].l = lower_bound(number.begin() + 1, number.begin() + newMagic, magic[i].l) - number.begin() ;
			magic[i].r = lower_bound(number.begin() + 1, number.begin() + newMagic, magic[i].r) - number.begin() ;
//			cerr << magic.magicL[i] << " " << magic[i].r[i] << '\n';
		}
		sort(magic + 1, magic + 1 + allMagic);
		for (int i = 1;i <= newMagic; ++i)
		{
			numberSize[i] = number[i] - number[i - 1];
			assert(numberSize[i] > 0);
//			cout <<
//			cout << numberSize[i] << '\n';
		}
	};

	function <int(int)> count = [&](int s)
	{
		int res = 0;
		while (s > 0)
			res ^= 1, s -= s & -s;
		return res;
	};

	function <void()> solve = [&]()
	{
		for (int i = 1;i <= newMagic; ++i)
			isMagicCovered[i].resize(limit + 1),
			isMagicEnd[i].resize(limit + 1);

		for (int i = 1; i <= limit; ++i)
		{
			int lowest = 0;
			for (int j = 1; j <= allMagic; ++j)
			{
				if (isUseed[j] || lowest >= magic[j].l)
					continue;
				isUseed[j] = 1;
//				cout << j << '\n';
				for (int k = magic[j].l; k <= magic[j].r; ++k)
					isMagicCovered[k][i] = 1;

				isMagicEnd[magic[j].r][i] = 1;
				lowest = magic[j].r;
			}
		}

		for (int i = 1; i <= newMagic; ++i)
		{
			for (int j = 1;j <= limit; ++j)
				magicCovered[i] |= (1 << j - 1) * int(isMagicCovered[i][j]),
				magicEnd[i] |= (1 << j - 1) * int(isMagicEnd[i][j]);
//			cout << magicCovered[i] << " " << magicEnd[i] << '\n';
		}

		int allBitMakes = 1 << limit;
		vector <int> f(allBitMakes + 1, 0);
		for (int i = 1; i < allBitMakes; ++i)
			f[i] = count(i);
		//	cout << f[i] << '\n';

		for (int i = 1; i <= newMagic; ++i)
		{
			for (int s = 0; s < allBitMakes; ++s)
			{
				if ((s | magicCovered[i]) != magicCovered[i])
					continue; dp[s] = 0;
				int basic = (s & magicCovered[i - 1]) & (magicCovered[i - 1] ^ magicEnd[i - 1]);
				for (int k = magicEnd[i - 1]; k; k = (k - 1) & magicEnd[i - 1])
					dp[s] = max(dp[s], maxValue[basic | k] + f[s] * numberSize[i]);

				dp[s] = max(dp[s], maxValue[basic] + f[s] * numberSize[i]);
//				cout << dp[s] << " " << numberSize[i] << '\n';
			}

			maxValue = dp;
		}

//		cout << number.size() << '\n';

		cout << *max_element(maxValue.begin(), maxValue.end()) << '\n';
	};

	init();
	solve();

	return 0;
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
#include <functional>
#include <iostream>
#include <queue>
#include <cassert>

using namespace std;
typedef long long int64;

int main()
{
	ios::sync_with_stdio(0), cin.tie(0);

	int allMagic = 0, m = 0, limit = 0, newMagic = 0;
	cin >> allMagic >> m >> limit;
	vector <int> magicL(allMagic + 1, 0);
	vector <int> magicR(allMagic + 1, 0);
	vector <int> number;
	vector <int64> dp(1 << limit | 1);
	vector <int64> maxValue(1 << limit | 1);
	vector <int64> numberSize;
	vector <int> magicCovered(allMagic * 5 + 1);
	vector <int> magicEnd(allMagic * 5 + 1);
	vector <vector <bool>> isMagicCovered(allMagic * 5 + 1);
	vector <vector <bool>> isMagicEnd(allMagic * 5 + 1);
	vector <bool> isUseed(allMagic + 1);

	function <void()> init = [&]()
	{
		for (int i = 1; i <= allMagic; ++i)
		{
			cin >> magicL[i] >> magicR[i];
			number.push_back(magicL[i]);
			number.push_back(magicR[i]);
			number.push_back(max(magicL[i] - 1, 1));
		}

		sort(number.begin(), number.end());
		newMagic = unique(number.begin(), number.end()) - number.begin();
//		for (int g : number)
//			cout << g << '\n';
		for (int i = 1; i <= allMagic; ++i)
		{
			magicL[i] = lower_bound(number.begin(), number.begin() + newMagic, magicL[i]) - number.begin() + 1;
			magicR[i] = lower_bound(number.begin(), number.begin() + newMagic, magicR[i]) - number.begin() + 1;
//			cout << magicL[i] << " " << magicR[i] << '\n';
		}

		numberSize.resize(number.size() + 3);
		for (int i = 1;i < newMagic; ++i)
		{
			numberSize[i] = number[i] - number[i - 1];
//			cout <<
			//cout << numberSize[i] << '\n';
		} numberSize[newMagic] = 1;
	};

	function <int(int)> count = [&](int s)
	{
		int res = 0;
		while (s > 0)
			res ^= 1, s -= s & -s;
		return res;
	};

	function <void()> solve = [&]()
	{
		for (int i = 1;i <= newMagic; ++i)
			isMagicCovered[i].resize(limit + 1),
			isMagicEnd[i].resize(limit + 1);

		for (int i = 1; i <= limit; ++i)
		{
			int lowest = 0;
			for (int j = 1; j <= allMagic; ++j)
			{
				if (isUseed[j] || lowest >= magicL[j])
					continue;
				isUseed[j] = 1;

				for (int k = magicL[j]; k <= magicR[j]; ++k)
					isMagicCovered[k][i] = 1;

				isMagicEnd[magicR[j]][i] = 1;
				lowest = magicR[j];
			}
		}

		for (int i = 1; i <= newMagic; ++i)
		{
			for (int j = 1;j <= limit; ++j)
				magicCovered[i] |= (1 << j - 1) * int(isMagicCovered[i][j]),
				magicEnd[i] |= (1 << j - 1) * int(isMagicEnd[i][j]);
//			cout << magicCovered[i] << " " << magicEnd[i] << '\n';
		}

		int allBitMakes = 1 << limit;
		vector <int> f(allBitMakes + 1, 0);
		for (int i = 1; i < allBitMakes; ++i)
			f[i] = count(i);
		//	cout << f[i] << '\n';

		for (int i = 1; i <= newMagic; ++i)
		{
			for (int s = 0; s < allBitMakes; ++s)
			{
				if ((s | magicCovered[i]) != magicCovered[i])
					continue;
				int basic = (s & magicCovered[i - 1]) & (magicCovered[i - 1] ^ magicEnd[i - 1]);
				for (int k = magicEnd[i - 1]; k; k = (k - 1) & magicEnd[i - 1])
				{
					dp[s] = max(dp[s], maxValue[basic | k] + f[s] * numberSize[i]);
				}

				dp[s] = max(dp[s], maxValue[basic] + f[s] * numberSize[i]);
//				cout << dp[s] << " " << numberSize[i] << '\n';
			}

			for (int s = 0;s < allBitMakes; ++s)
				maxValue[s] = dp[s],
				dp[s] = 0;
		}

//		cout << number.size() << '\n';

		cout << *max_element(maxValue.begin(), maxValue.end()) << '\n';
	};

	init();
	solve();

	return 0;
}


/*#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
#pragma target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")*/
#include<bits/stdc++.h>
#define ll long long
#define inf 1000000005
#define mod 1000000007
#define put putchar('\n')
#define F(i,a,b) for (int i=(a);i<=(b);i++)
#define D(i,a,b) for (int i=(a);i>=(b);i--)
#define R(i,a,b) for (int i=(a);i<(b);i++)
#define go(i,t) for (int i=head[t];i;i=Next[i])
#define sqr(x) ((x)*(x))
#define re register
#define mp make_pair
#define fi first
#define se second
#define pa pair<int,int>
#define pb push_back
#define be begin()
#define en end()
#define ret return puts("-1"),0;
#define N 500055
#define int ll
using namespace std;
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){char c=getchar();int tot=1;while ((c<'0'|| c>'9')&&c!='-') c=getchar();if (c=='-'){tot=-1;c=getchar();}
int sum=0;while (c>='0'&&c<='9'){sum=sum*10+c-'0';c=getchar();}return sum*tot;}
inline void wr(int x){if (x<0) {putchar('-');wr(-x);return;}if(x>=10)wr(x/10);putchar(x%10+'0');}
inline void wrn(int x){wr(x);put;}inline void wri(int x){wr(x);putchar(' ');}
inline void wrn(int x,int y){wri(x);wrn(y);}inline void wrn(int a,int b,int c){wri(a);wrn(b,c);}
int n,m,k,c[N],tot,t,yk[N],dp1[N],dp2[N],cn,p[N],q[N],wzp,vis[N],g[N],ans;
struct xx{
	int l,r;
}z[N];
bool cmp(xx a,xx b){
	return a.l==b.l?a.r<b.r:a.l<b.l;
}
void dfs(int x,int k,int p1){
	if (x==t+1){
		yk[k]=max(yk[k],dp1[p1]);
		return;
	}
	dfs(x+1,k,p1);
	dfs(x+1,k+(p[x]?1<<(p[x]-1):0),p1+(1<<(x-1)));
}
void dfs2(int x,int k,int p1,int p2){
	if (x==cn+1){
		dp2[p1]=yk[k]+(p2?wzp:0);
		return;
	}
	dfs2(x+1,k,p1,p2);
	dfs2(x+1,k+(vis[x]?(1<<(x-1)):0),p1+(1<<(x-1)),p2^1);
}
signed main(){
	n=read();m=read();k=read();
	F(i,1,n){z[i].l=read();z[i].r=read();c[++tot]=z[i].l;c[++tot]=z[i].r;}
	sort(c+1,c+tot+1);
	tot=unique(c+1,c+tot+1)-c-1;
	F(i,1,n){
		z[i].l=lower_bound(c+1,c+tot+1,z[i].l)-c;
		z[i].r=lower_bound(c+1,c+tot+1,z[i].r)-c;
	}
	sort(z+1,z+n+1,cmp);
	int l=1;
	R(i,1,tot){
		wzp=c[i+1]-c[i];
		cn=0;
		F(j,1,t) p[j]=vis[j]=0;
		F(j,1,t){
			if (g[j]!=i) q[++cn]=g[j],p[j]=cn;
			vis[cn]=1;
		}
		while (z[l].l==i) q[++cn]=z[l++].r;
		dfs(1,0,0);
		dfs2(1,0,0,0);
		t=cn;F(j,1,t) g[j]=q[j];
		R(j,0,(1<<t)) dp1[j]=dp2[j],dp2[j]=0;
		R(j,0,(1<<t)) yk[j]=0;
	}
	R(i,0,(1<<t)) ans=max(ans,dp1[i]);
	wrn(ans);
	return 0;
}


/*#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
#pragma target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")*/
#include<bits/stdc++.h>
#define ll long long
#define inf 1000000005
#define mod 1000000007
#define put putchar('\n')
#define F(i,a,b) for (int i=(a);i<=(b);i++)
#define D(i,a,b) for (int i=(a);i>=(b);i--)
#define R(i,a,b) for (int i=(a);i<(b);i++)
#define go(i,t) for (int i=head[t];i;i=Next[i])
#define sqr(x) ((x)*(x))
#define re register
#define mp make_pair
#define fi first
#define se second
#define pa pair<int,int>
#define pb push_back
#define be begin()
#define en end()
#define ret return puts("-1"),0;
#define N 500055
#define int ll
using namespace std;
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){char c=getchar();int tot=1;while ((c<'0'|| c>'9')&&c!='-') c=getchar();if (c=='-'){tot=-1;c=getchar();}
int sum=0;while (c>='0'&&c<='9'){sum=sum*10+c-'0';c=getchar();}return sum*tot;}
inline void wr(int x){if (x<0) {putchar('-');wr(-x);return;}if(x>=10)wr(x/10);putchar(x%10+'0');}
inline void wrn(int x){wr(x);put;}inline void wri(int x){wr(x);putchar(' ');}
inline void wrn(int x,int y){wri(x);wrn(y);}inline void wrn(int a,int b,int c){wri(a);wrn(b,c);}
int n,m,k,c[N],tot,t,yk[N],dp1[N],dp2[N],cn,p[N],q[N],wzp,vis[N],g[N],ans;
struct xx{
	int l,r;
}z[N];
bool cmp(xx a,xx b){
	return a.l==b.l?a.r<b.r:a.l<b.l;
}
void dfs(int x,int k,int p1){
	if (x==t+1){
		yk[k]=max(yk[k],dp1[p1]);
		return;
	}
	dfs(x+1,k,p1);
	dfs(x+1,k+(p[x]?1<<(p[x]-1):0),p1+(1<<(x-1)));
}
void dfs2(int x,int k,int p1,int p2){
	if (x==cn+1){
		dp2[p1]=yk[k]+(p2?wzp:0);
		return;
	}
	dfs2(x+1,k,p1,p2);
	dfs2(x+1,k+(vis[x]?(1<<(x-1)):0),p1+(1<<(x-1)),p2^1);
}
signed main(){
	n=read();m=read();k=read();
	F(i,1,n){z[i].l=read();z[i].r=read()+1;c[++tot]=z[i].l;c[++tot]=z[i].r;}
	sort(c+1,c+tot+1);
	tot=unique(c+1,c+tot+1)-c-1;
	F(i,1,n){
		z[i].l=lower_bound(c+1,c+tot+1,z[i].l)-c;
		z[i].r=lower_bound(c+1,c+tot+1,z[i].r)-c;
	}
	sort(z+1,z+n+1,cmp);
	int l=1;
	R(i,1,tot){
		wzp=c[i+1]-c[i];
		cn=0;
		F(j,1,t) p[j]=vis[j]=0;
		F(j,1,t){
			if (g[j]!=i) q[++cn]=g[j],p[j]=cn;
			vis[cn]=1;
		}
		while (z[l].l==i) q[++cn]=z[l++].r;
		dfs(1,0,0);
		dfs2(1,0,0,0);
		t=cn;F(j,1,t) g[j]=q[j];
		R(j,0,(1<<t)) dp1[j]=dp2[j],dp2[j]=0;
		R(j,0,(1<<t)) yk[j]=0;
	}
	R(i,0,(1<<t)) ans=max(ans,dp1[i]);
	wrn(ans);
	return 0;
}
/*
1 1 1
1 1
*/


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=1e5+10;
struct apple{
    int x,id,f;
    bool operator <(const apple &other)
    const {
        return x<other.x||(x==other.x&&f>other.f)||(x==other.x&&f==other.f&&id<other.id);
    }
}node[N*2];
int h[N*2];
int que[10];
int f[1030],ff[1030];
int now;
int get_num(int x)
{
    int ans=0;
    while(x)
    {
        if(x&1)
            ans++;
        x>>=1;
    }
    return ans;
}
void del(int id)
{
    int pos,i,j;
    for(pos=1;pos<=now;pos++)
        if(que[pos]==id)
            break;
    for(i=1;i<(1<<now);i++)
        ff[i]=0;
    for(i=0;i<(1<<now);i++)
    {
        j=i%(1<<(pos-1))+(i>>pos);
        ff[j]=max(ff[j],f[i]);
    }
    now--;
    for(i=pos;i<=now;i++)
        que[i]=que[i+1];
    for(i=0;i<(1<<now);i++)
        f[i]=ff[i];
}
void ins(int id)
{
    int i;
    for(i=0;i<(1<<now);i++)
        f[(1<<now)+i]=f[i];
    que[++now]=id;
}
void solve(int id)
{
    int i;
    for(i=0;i<(1<<now);i++)
        if(get_num(i)%2==1)
            f[i]+=h[id+1]-h[id];
    /*for(i=1;i<=now;i++)
        printf("%d ",que[i]);
    printf("\n");
    for(i=0;i<(1<<now);i++)
        printf("%d ",f[i]);
    printf("\n\n");*/
}
int main()
{
    int n,m,k,cnt,l,i,j,r,ans=0;
    cnt=0;
    scanf("%d%d%d",&n,&m,&k);
    for(i=1;i<=n;i++)
    {
        scanf("%d%d",&l,&r);
        h[++cnt]=l;
        node[cnt].x=l;
        node[cnt].f=0;
        node[cnt].id=i;
        h[++cnt]=r+1;
        node[cnt].x=r+1;
        node[cnt].f=1;
        node[cnt].id=i;
    }
    h[++cnt]=m+1;
    sort(h+1,h+cnt+1);
    l=unique(h+1,h+cnt+1)-h-1;
    /*printf("<%d>",l);
    for(i=1;i<=l;i++)
        printf("%d ",h[i]);
    printf("\n");*/
    sort(node+1,node+cnt);
    j=1;
    now=0;
    for(i=1;i<=l;i++)
    {
        while(j<cnt&&node[j].x<=h[i])
        {
            if(node[j].f==0)
                ins(node[j].id);
            else
                del(node[j].id);
            j++;
        }
        solve(i);
    }
    for(i=0;i<(1<<now);i++)
        ans=max(ans,f[i]);
    printf("%d",ans);
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=1e5+10;
struct apple{
    int x,id,f;
    bool operator <(const apple &other)
    const {
        return x<other.x||(x==other.x&&f>other.f)||(x==other.x&&f==other.f&&id<other.id);
    }
}node[N*2];
int h[N*2];
int que[10];
int f[1030],ff[1030];
int now;
int get_num(int x)
{
    int ans=0;
    while(x)
    {
        if(x&1)
            ans++;
        x>>=1;
    }
    return ans;
}
void del(int id)
{
    int pos,i,j;
    for(pos=1;pos<=now;pos++)
        if(que[pos]==id)
            break;
    for(i=0;i<(1<<now);i++)
        ff[i]=0;
    for(i=0;i<(1<<now);i++)
    {
        j=i%(1<<(pos-1))+(i>>pos)<<(pos-1);
        ff[j]=max(ff[j],f[i]);
    }
    now--;
    for(i=pos;i<=now;i++)
        que[i]=que[i+1];
    for(i=0;i<(1<<now);i++)
        f[i]=ff[i];
}
void ins(int id)
{
    int i;
    for(i=0;i<(1<<now);i++)
        f[(1<<now)+i]=f[i];
    que[++now]=id;
}
void solve(int id)
{
    int i;
    for(i=0;i<(1<<now);i++)
        if(get_num(i)%2==1)
            f[i]+=h[id+1]-h[id];
    /*for(i=1;i<=now;i++)
        printf("%d ",que[i]);
    printf("\n");
    for(i=0;i<(1<<now);i++)
        printf("%d ",f[i]);
    printf("\n\n");*/
}
int main()
{
    int n,m,k,cnt,l,i,j,r,ans=0;
    cnt=0;
    scanf("%d%d%d",&n,&m,&k);
    for(i=1;i<=n;i++)
    {
        scanf("%d%d",&l,&r);
        h[++cnt]=l;
        node[cnt].x=l;
        node[cnt].f=0;
        node[cnt].id=i;
        h[++cnt]=r+1;
        node[cnt].x=r+1;
        node[cnt].f=1;
        node[cnt].id=i;
    }
    h[++cnt]=m+1;
    sort(h+1,h+cnt+1);
    l=unique(h+1,h+cnt+1)-h-1;
    /*printf("<%d>",l);
    for(i=1;i<=l;i++)
        printf("%d ",h[i]);
    printf("\n");*/
    sort(node+1,node+cnt);
    j=1;
    now=0;
    for(i=1;i<=l;i++)
    {
        while(j<cnt&&node[j].x<=h[i])
        {
            if(node[j].f==0)
                ins(node[j].id);
            else
                del(node[j].id);
            j++;
        }
        solve(i);
    }
    for(i=0;i<(1<<now);i++)
        ans=max(ans,f[i]);
    printf("%d",ans);
    return 0;
}