// 这个B非常NOIP
# include <bits/stdc++.h>
# define wheneveright bool mem2; signed main
using namespace std;

bool mem1;

const int maxn = 2000005;
const int maxm = 605;

struct reader {
	template <typename Type>
	reader & operator >> (Type & ret) {
		int f = 1; ret = 0; char ch = getchar ();
		for (;!isdigit (ch); ch = getchar ()) if (ch == '-') f = -f;
		for (; isdigit (ch); ch = getchar ()) ret = ret * 10 + ch - '0';
		ret *= f; return * this;
	}
} fin;

// This n, m is not same with the problem
int T, n, m, k, nxt_c[maxn];
int a[maxn], nxt[maxn], now[maxm];
deque < int > que[maxn], S;
struct WER {
	int pos, nxt;
	bool operator < (WER p) const {
		return nxt < p.nxt || (nxt == p.nxt && pos < p.pos);
	}
} ;
multiset < WER > KW, DD, DF;
// siz = 0, vi < vi+1, up to down
vector < vector < int > > res;

wheneveright () {
	cerr << "Memory Cost : " << abs (& mem1 - & mem2) / 1024. / 1024. << " MB\n";
	freopen ("meow.in", "r", stdin);
	freopen ("meow.out", "w", stdout);
	fin >> T;
	if (T % 10 <= 1 || T % 10 == 5) while (T--) {
		fin >> m >> n >> k; res.clear (); S.clear ();
		for (int i = 1; i <= k; i++) now[i] = 0;
		for (int i = 1; i <= m; i++) S.push_back (i);
		for (int i = 1, x; i <= n; i++) {
			fin >> x;
			if (!now[x]) {
				int t = S.front (); S.pop_front ();
				que[t].push_back (x);
				if (int (que[t].size ()) < 2) S.push_back (t);
				now[x] = t;
				res.push_back ({ 1, t });
			}
			else {
				if (que[now[x]].front () == x) {
					res.push_back ({ 1, m });
					res.push_back ({ 2, now[x], m });
					que[now[x]].pop_front ();
				}
				else {
					res.push_back ({ 1, now[x] });
					que[now[x]].pop_back ();
				}
				if (int (que[now[x]].size ()) < 2) S.push_back (now[x]);
				now[x] = 0;
			}
		}
		printf ("%d\n", int (res.size ()));
		for (auto i : res) {
			for (auto j : i) printf ("%d ", j);
			putchar (10);
		}
	} // 破防了
	else while (T--) {
		fin >> m >> n >> k; res.clear ();
		KW.clear (); DD.clear (); DF.clear ();
		for (int i = 1; i <= n; i++) fin >> a[i];
		for (int i = 1; i <= k; i++) now[i] = n + 1;
		for (int i = n; i >= 1; i--) {
			nxt[i] = now[a[i]];
			now[a[i]] = i;
		}
		for (int i = 1; i < m; i++) KW.insert ((WER) { i, 0 });
		for (int i = 1; i <= k; i++) now[i] = nxt_c[i] = 0;
		for (int i = 1; i <= n; i++) {
			nxt_c[a[i]] = nxt[i];
			if (now[a[i]]) {
				auto it = DD.end ();
				if (que[now[a[i]]].front () == a[i]) {
//					printf ("1 %d\n", m);
//					printf ("2 %d %d\n", now[a[i]], m);
					res.push_back ({ 1, m });
					res.push_back ({ 2, now[a[i]], m });
					que[now[a[i]]].pop_front ();
					if (que[now[a[i]]].empty ()) {
						KW.insert ((WER) { now[a[i]], 0 });
						if ((it = DD.find ((WER) { now[a[i]], i })) != DD.end ()) DD.erase (it);
						if ((it = DF.find ((WER) { now[a[i]], i })) != DF.end ()) DF.erase (it);
					}
				}
				else {
//					printf ("1 %d\n", now[a[i]]);
					res.push_back ({ 1, now[a[i]] });
					if ((it = DD.find ((WER) { now[a[i]], i })) != DD.end ()) DD.erase (it);
					if ((it = DF.find ((WER) { now[a[i]], i })) != DF.end ()) DF.erase (it);
					que[now[a[i]]].pop_back ();
					if (que[now[a[i]]].empty ())
						KW.insert ((WER) { now[a[i]], 0 });
					else if (int (que[now[a[i]]].size ()) == 1)
						DD.insert ((WER) { now[a[i]], nxt_c[que[now[a[i]]].back ()] });
					else {
						int x = que[now[a[i]]].back (); que[now[a[i]]].pop_back ();
						int y = que[now[a[i]]].back (); que[now[a[i]]].push_back (x);
						if (nxt_c[x] > nxt_c[y]) DD.insert ((WER) { now[a[i]], nxt[que[now[a[i]]].back ()] });
						else DF.insert ((WER) { now[a[i]], nxt[que[now[a[i]]].back ()] });
					}
				}
				now[a[i]] = 0;
			}
			else {
				auto it = DD.lower_bound ((WER) { 0, nxt[i] }); int p;
				if (it != DD.begin ()) {
					it--;
					WER x = *it;
					DD.erase (it);
					que[x.pos].push_back (a[i]);
					DD.insert ((WER) { x.pos, nxt[i] });
					now[a[i]] = x.pos;
					goto Loop ;
				}
				it = DF.lower_bound ((WER) { 0, nxt[i] });
				if (it != DF.begin ()) {
					it--;
					WER x = *it;
					DF.erase (it);
					que[x.pos].push_back (a[i]);
					DF.insert ((WER) { x.pos, nxt[i] });
					now[a[i]] = x.pos;
					goto Loop ;
				}
				it = DD.upper_bound ((WER) { 0, nxt[i] });
				if (it != DD.end ()) {
					WER x = *it;
					DD.erase (it);
					que[x.pos].push_back (a[i]);
					DF.insert ((WER) { x.pos, nxt[i] });
					now[a[i]] = x.pos;
					goto Loop ;
				}
				p = (*KW.begin ()).pos; KW.erase (KW.begin ());
				que[p].push_back (a[i]);
				DD.insert ((WER) { p, nxt[i] });
				now[a[i]] = p;
				Loop : ; res.push_back ({ 1, now[a[i]] });
			}
		}
		printf ("%d\n", int (res.size ()));
		for (auto i : res) {
			for (auto j : i) printf ("%d ", j);
			putchar (10);
		}
	}
	return 0;
}